目录
2.1 Instant vector selectors(即时向量选择器)
2.2 Range Vector Selectors(区间向量选择器)
在这篇简单介绍一下PromQL(Prometheus Query Language),即Prometheus查询语言。
可以先简单看一下prom官方文档QUERYING PROMETHEUS
一、PromQL介绍
1.1 时序数据库
1.1.1 介绍
时序数据库(Time Series Database,TSDB)用于保存时间序列(按时间顺序变化)的海量数据,是一种高性能、低成本、稳定可靠的专业化数据库。它可以提供高效读写、高压缩比低成本存储、降精度、插值、多维聚合计算和查询功能,解决由于设备采集点数据量巨大、数据采集频率高而造成的存储成本高、写入和查询分析效率低的问题。时序数据库广泛应用于物联网监控系统、企业能源管理系统、生产安全监控、电力检测系统等行业场景。
Google的监控系统经过10年的发展,经历了从传统的探针模型、图形化趋势展示模型到现在的基于时间序列数据信息进行监控报警的新模型。新模型将收集时间序列信息作为监控系统的首要任务,同时发展了一种时间序列信息操作语言,通过该语言将数据转化为图标和告警,从而取代了以前的探针脚本。
从2014年开始,时序数据库被DB-Engines列入了单独的数据库类别进行统计。在DB-Engines网站上可
以看到近期时序数据库的Top 10列表
在时序数据库的发展史中,通用关系数据库是可以存储时序数据的,但是由于其缺乏针对时间的特殊优化,例如按时间间隔存储和检索数据,因此在处理数据时效率相对低。接着出现了源于监控领域的首代时序数据存储系统,直接基于平板文件的简单存储工具成为这类数据的首选存储方式,以RRDTool、Wishper为代表,通常这类系统处理的数据模型比较单一,单机容量受限,并且内嵌于监控告警方案。
随着互联网大数据技术的出现和快速发展,时序数据量也开始迅速增长,系统业务对处理时序数据的扩展性等方面提出更多的要求。基于通用存储而专门构建的时间序列数据库开始出现,它可以按时间间隔高效地存储和处理这些数据。以OpenTSDB、KairosDB为代表,这类时序数据库在继承通用存储优势的基础上,利用时序的特性规避部分通用存储的劣势,并且在数据模型以及聚合分析方面做了贴合时序的大量创新。
随着虚拟化技术的发展以及Docker、Kubernetes、微服务等技术的应用,高性能、低成本的垂直型时序数据库诞生了,以InfluxDB为代表,具有时序特征的数据存储引擎逐步引领市场。它们通常具备更加高级的数据处理能力、高效的压缩算法和符合时序特征的存储引擎。近年来时序数据库高速发展,国内外云市场各大主流厂商已经从整个时序生态的不同角度切入,形成各具特色的解决方案布局,开始抢占市场流量。未来,相信时序技术领域将会出现因黑科技不断涌现而形成的百家争鸣的生态技术场景。
1.1.2 特性
数据写入特点——写入平稳、持续、高并发高吞吐;写多读少,在写操作上时序数据能达到95%以上;无更新实时写入最近生成的数据。
数据查询特点——按时间范围读取一段时间的数据;对最近生成的数据读取概率高,对历史数据查询概率低;按照数据点的不同密集度实现多精度查询
数据存储特点——数据存储量比较大;具有时效性,数据通常会有一个保存周期;多精度数据存储。
对时序数据库的基本要求如下:
- 能够支撑高并发、高吞吐的写入。
- 交互级的聚合查询,能够达到低查询延迟。
- 依据场景设计可以支撑海量数据存储。
- 在线应用服务场景中,需要高可用架构支撑。
- 针对写入和存储量的要求,应用环境底层需要分布式架构支持。
1.2 PromQL简介
1.2.1 PromQL简介
PromQL虽然以QL结尾,但它不是类似SQL的语言,因为在时间序列上执行计算类型时,SQL语言相对缺乏表达能力。而PromQL语言表现力非常丰富,可以使用标签进行任意聚合,还可以使用标签将不同的指标连接在一起进行算术操作。内置了日期和数学等很多的函数可供使用。
下面我们对Prometheus查询语言PromQL的一些知识点做简要介绍。也可以看一下官方文档QUERYING PROMETHEUS相半说明
1.2.2 数据模型与数据类型
Prometheus发布的2.0版本是一个完全重写的新存储引擎,新版本变化比较大,不对旧版本做兼容升级。它使用的底层存储具备了完整的持久化方案。Prometheus与其他主流时序数据库一样,在数据模型的核心定义上,一条Prometheus数据会包含一个指标名称(metric name)和一个或多个标签(label)以及metricvalue。metric name加一组label作为唯一标识来定义time series,也就是时间线。在查询时,支持根据labels条件查找time series,支持简单的条件也支持复杂的条件。我们可以看下面的实例数据:
promhttp_metric_handler_requests_total{code="200",instance="192.168.24.17:9090",job="prometheus"} 247668
在此数据中指标名称为“promhttp_metric_handler_requests_total”,已经知道Prometheus提供了四种核心metric类型,分别Counter、Gauge、Historgram和Summary。该条数据中包括的标签有code、instance、job,该数据记录的值是247668。
根据时序数据的特点,可以通过一张简单的数据点分布视图来体现时序数据存储的垂直写水平读,如下面的
时序数据点分布视图:
横轴是时间,纵轴是时间线,区域内的点就是数据点。可以形象地表述为Prometheus每次接收数据,收到的是图中区域内纵向的一条线。因为在同一时刻,每条时间线只会产生一个数据点,但同时会有多条时间线产生数据,把这些数据点连在一起,就是一条竖线。这个特征很重要,影响数据写入和压缩的优化策略。
在Prometheus的表达式语言中,PromQL数据类型归类为以下四种:
即时向量(instant vector):是指同一时刻的一组时间序列,每个时间序列包含一个样本,所有样本共享相同的时间戳,即每个时序只有一个点。
区间向量(range vector):是指在任何一个时间范围内的一组时间序列,包含每个时间序列随时间变化的一系列数据点,这时每个时序有多个点。
标量(scalar):即纯量数据,一个简单的数字浮点值,只有一个数字,没有时序。
字符串(string):一个目前未被使用的简单字符串值。
二、 PromQL 时间序列选择器
2.1 Instant vector selectors(即时向量选择器)
我们可以将“Instant vector selectors”称为“即时向量选择器”。它返回查询计算时间之前的最新样本的即时向量,即一个包含零个或多个时间序列的列表。这些时间序列中的每一个都有一个样本,样本包含值和时间戳。在最简单的形式中,只指定一个指标名称,这将生成一个包含所有时间序列元素的即时向量,这些元素都具有这个指标名称。
下面我们举一个最简单的例子,也就是PromQL直接输入监控指标的指标名称。通过在Prometheus WebUI中的Graph页面中输入用于target的健康检查的“UP”表达式,再点击“Execute”进行查询,在Console栏目中可以看到Prometheus抓取到的所有target的当前运行情况
上面也可以详细指定,如输入 up{instance="192.168.3.21:9100"}
通过在花括号({})中添加一组匹配的标签,便可以进一步过滤这些时间序列。这就是Instant vector selectors写法,这里仅仅使用“=”号,除此之外还可以对标签值进行反向匹配,或者将标签值与正则表达式进行匹配
运算符 | 描述 |
---|---|
= | 相等匹配模式,用来指定返回的时间序列具有与给定标签值完全相同的标签名称,例如,job="centos8" |
!= | 反向匹配模式,即不等于模式,用来指定返回的时间序列没有与给定标签值完全相同的标签名称,例如,job!="redis_ exporter" |
=~ | 正则表达式匹配模式,使用此运算符,可以指定对于返回的时间序列,给定标签的值将由正则表达式匹配。 正则表达式是完全锚定的,也就是说正则表达式x只匹配字符串x,而不匹配xy或yx。 |
!~ | 反向正则表达式匹配模式,选择不匹配正则表达式的标签(或子标签),例如,up{job !~ "nginx-. *"} |
在选择器中,相同的标签名称可以有多个匹配模式。例如,要查找安装在/run而不是/run/user下的所有文件系统的大小,可以使用:
node_filesystem_size_bytes{job="node",mountpoint=~"/run/.*",mountpoint!~"/run/user/.*"}
在以上列举的选择器中我们使用了{},以避免返回Prometheus服务器内的所有时间序列,浪费系统资源。所以向量选择器必须指定一个名称或至少一个与空字符串不匹配的标签匹配模式。现在看一下{job=~".*"}表达式,它的使用是不合法的。而{job=~".+"}和{job=~".*",method="get"}表达式均是有效合法的,因为它们都有一个与空标签值不匹配的选择器。另外,通过匹配内部__name__标签,还可以将标签匹配模式应用于监控指标的标准名称。例如,表达式http_requests_total等效于{__name__="http_requests_total"}。也可以使用除=(!=,=~,!~)之外的匹配模式。以下表达式选择名称以job:开头的所有指标:{__name__=~"job:.*"}。当然也可以对指标名称执行正则表达式,但是在调试Prometheus服务器的性能时,不建议执行这样的操作。
2.2 Range Vector Selectors(区间向量选择器)
与每个时间序列返回一个样本的即时向量选择器不同,区间向量选择器可以为每个时间序列返回许多样本。从语法上看,范围持续时间被添加到向量选择器末尾的方括号[]中,用来指定我们想获取的过去一段时间范围内的样本数据。
它的经常单位如下:
S - seconds,秒
m - minutes,分
h- hours,时
d - days,天
W一weeks,周
y - years,年
例如,使用浏览器直接在Prometheus Web UI中的Graph页面中输入process_cpu_seconds_total[1m],然后在Console选项卡中执行,可以看到,每个时间序列在过去一分钟内有3个样本,如下图:
2.3 Offset modifier(偏移量修改器)
Offset modifier(偏移量修改器),在即时向量表达式或区间向量表达式中,都以当前时间作为基准,例如:
# 即时向量表达式,选择当前最新的数据
process_resident_memory_bytes{ job="prometheus"}
# 区间向量表达式,选择以当前时间为基准的15分钟内的数据
process_resident_memory_bytes{ job="prometheus"} [15m]
如果想查询15分钟前的即时样本数据,或昨天一天内的样本数据时,就需要使用本小节的时间偏移操作了,此操作使用的关键字为offset,可以分别做如下操作:
process_resident_memory_bytes{ job="prometheus"} offset 15m
process_resident_memory_bytes{ job="prometheus"} [1d]offset 1d
可以看到,时间偏移操作允许更改查询中各个即时向量或区间向量的时间偏移量。但是,在以上这些简单查询中,我们很少使用时间偏移操作,因为,例如在Prometheus Web UI上通过更改时间查询范围就能容易实现。而实际使用时间偏移操作更多的是如下操作:
process_resident_memory_bytes{ job="prometheus"}
# 给出prometheus在过去一小时内内存使用量的变化
process_resident_memory_bytes{ job="prometheus"}offset 1h
# 同样的操作方法也适用于区间向量
#rate()函数,即计算某个时间序列范围内的平均增长率
#当前时间15分钟内平均增长率
rate(process_resident_memory_bytes{ job="prometheus"} [15m])
#返回1小时前,15分钟内,平均增长率
rate(process_resident_memory_bytes{ job="prometheus"} [15m]offset 1h)