PromQL计算原理详解

本文涉及的产品
可观测监控 Prometheus 版,每月50GB免费额度
简介: ## 背景PromQL是Prometheus项目针对时序场景提供的一种查询语言,而PromQL的设计与常规意义上的SQL语句区别较大,其执行引擎的计算逻辑同样也大相径庭。在日常的客服解答中,发现较多客户对PromQL的执行原理有误解,故整理此篇文章对PromQL的原理与执行逻辑进行详细介绍。## 对时序的认识时序场景下的观测对象是 “Metric”,例如这项表示“进程的常驻内存使用量

背景

PromQL是Prometheus项目针对时序场景提供的一种查询语言,而PromQL的设计与常规意义上的SQL语句区别较大,其执行引擎的计算逻辑同样也大相径庭。在日常的客服解答中,发现较多客户对PromQL的执行原理有误解,故整理此篇文章对PromQL的原理与执行逻辑进行详细介绍。

对时序的认识

时序场景下的观测对象是 “Metric”,例如这项表示“进程的常驻内存使用量”的指标Metric process_resident_memory_bytes 。首先介绍“时间线”的概念,Prometheus通过多个Label标签值来区分不同的时间线,从下图我们可以看到该指标存在三条时间线,分别是:

时间线1: instance="demo.promlabs.com:10000", job="demo"
时间线2: instance="demo.promlabs.com:10001", job="demo"
时间线3: instance="demo.promlabs.com:10002", job="demo"


上述三条时间线存在两个Label标签,分别为表示“进程”的job和表示实例instance。从现实意义上看process_resident_memory_bytes这项指标,绿色折线即表示进程名为”demo“且实例名为“demo.promlabs.com:10000”的一个进程的常驻内存占用情况。Metric时序场景中,不同的Label值列表则表示一条新的时间线,每个Label都由Key/Value值组成,例如 job="demo" 这个Label中的Key值为“job”、Value值为“demo”。下面给出了Label在源码中的数据结构定义,

type Label struct {
    Name, Value string
}

接着介绍Promethus时序模型中的“采样点”,每个采样点由Label列表、时间戳、数值组成,下面同样给出了数据结构的定义,

type Point struct {
    T int64  // 时间戳, ms精度
    V float64 // 数值
}

type Sample struct {
    Point
    lables []Label  // Label列表
}

数据采集

Prometheus通过http访问目标进程实例的/metrics接口拉取指标数据,而指标拉取的时间间隔(例如,5秒)可通过配置文件进行自定义配置。我们假设拉取到的指标仍是process_resident_memory_bytes、时间线仍是前面列举的三条时间线、每隔5秒拉取一次指标,那么在查询近10分钟的数据时,理论上会有 600/5*3+3 (即 363) 个数据点。以 00:00 ~ 10:00为例,指标采样点的时间戳分别为00:05/00:10/00:15.........09:50/09:55/10:00,示例图可见下图:

上图给出了指标采样点的示例图,而在实际的生产环境中,采样的时间戳并不会如此规整。例如发起采样的时间点为00:03,那么后续的时间点则为00:08/00:13/00:18......;此外,受并发、网络延时等影响,采集间隔也可能不会完全严格遵守5秒间隔的约束。

PromQL Engine执行原理

前文介绍了Prometheus中的时序模型、时间线、采样点等概念,接下来将介绍Prometheus计算引擎执行时序查询的的原理。Prometheus为时序查询提供了时序查询设计了一种查询语言,即PromQL(Prometheus query language)。

查询分类

在实际的生产环境中,PromQL的使用主要可分为两种:纯查询型、计算型。

  • 纯查询型的PromQL

此类型的PromQL不包含任何计算步骤,仅从Metric的原始指标数据中筛选出符合条件的所有时间线数据。例如,Metric{}Metric{job="demo"}

  • 计算型的PromQL

此类型的PromQL包含聚合算子、一/二元计算表达式、函数等所有涉及了计算过程的查询语句。例如,max(Metric), irate(Metric[1m]), Metric + 1

另外,Prometheus为时序查询提供了/queryquery_range两个查询接口:

  • /query接口

此接口仅会返回当前时间戳下的各时间线的最新值。

  • /query_range接口

此接口会返回 start 到 end 这个时间区间内各时间线的多个值,后续都以 /query_range 接口为例进行解析。

计算过程

PromQL引擎的执行逻辑与常见的SQL执行方式差异较大,此处将分别介绍“纯查询型”和“计算型”两种类型PromQL的计算过程。

step参数

这里首先介绍执行PromQL计算时一项必须的参数step,理解了该参数的含义才能更好的理解PromQL的计算原理。

该参数表示执行计算的间隔区间,即表示从startTime开始每间隔step的长度都执行一轮计算。通过下图来展示step参数的含义:从00:00时间开始,每间隔40s执行一轮计算,总计将执行16轮计算。

PromQL的所有查询计算都遵循上述这个”每间隔step执行一轮计算“流程,而几类PromQL的区别主要就体现在”每轮计算“中,即”每轮计算“的执行逻辑差异较大。

纯查询型

/query_range的查询主要有以下四个参数:

query, 表示查询语句, 例如 up{instance="1"}
start, 表示查询区间的起始时间戳, 以秒为单位
end,   表示查询区间的截止时间戳,以秒为单位
step,  表示查询时的位移, 以秒为单位

执行查询时首先会根据start和end两个参数拉取到时间范围内的所有数据点,此处以数据采集一节中的数据为案例。

假设 start/end/step三个参数分别为“0, 600, 15”,即首先会将363个数据点都加载到内存中,其次进入到 “选点” 过程。此处的”选点“过程是Prometheus中一种特殊逻辑,流程如下:

  1. 从start时间戳开始,每间隔 step 的时长会选取一个点值,直至end时间戳结束。以上述案例为例,每条时间线都会进行 600/15+1(即,41)次数据点选取。
  2. 每次选取数据点的时候,会往前回溯n分钟(默认5分钟)并找到离当前时间戳最近的作为当前时间戳的值。用下图解释这种回溯逻辑,例如原始数据中在 09:28 时刻并不存在数据点,此时会选择 09:25 时刻作为当前时间戳的数据。


在此类型的PromQL查询中,每间隔step执行的”每轮计算“实际仅为数据选取,并未涉及到任何计算过程。针对每条时间线都会进行上述的”选点“处理,那么最后的结果会有41x3(即,123)个数据点。这样就完成了”纯查询型“PromQL的执行流程,最后将结果展示在页面之上。

计算型

计算型的PromQL存在两种计算模式,这里我将它们简称为”纵向“和”横向“计算。例如,max(metric)属于“纵向计算”、max_over_time(metric[30s])属于“横向计算”。下面分别以这两个PromQL来介绍两种截然不同的执行逻辑。

  • 纵向计算 -- max(metric)

在每间隔“step”执行一轮计算时,会选取当前时间戳下所有时间线的数据并执行计算,此时的数据选取逻辑与“纯查询型”PromQL一致。例如当前存在n条时间线,那么每次计算都是从n个value中选一个最大的值,且最后的结果仅存在一条折线。如果仍然以前述的数据为例子,123个数据点经计算后的结果仅存在41个数据点。


实际上,这种纵向计算模式对应了Prometheus中的 InstantVectorSelector

  • 横向计算 -- max_over_time(metric[30s])

首先同样是每间隔“step”会执行一次计算,但是计算时则是单独会针对每条时间线进行一次计算。在执行“横向”计算时,那么自然需要“横向”选取数据点。针对此类型的query,需要一个额外的参数“range”,该参数表示横向选取的时间范围。以下面的query为例,

query, 表示查询语句, 例如 max_over_time(metric[30s]), 在这个query中还存在range参数, 即 ”30s“
start, 表示查询区间的起始时间戳, 以秒为单位
end,   表示查询区间的截止时间戳,以秒为单位
step,  表示查询时的位移, 以秒为单位

假设 start、end、step参数分别为”0、600、1m“

上述例子表示每间隔1分钟执行一轮计算,每轮计算都会针对每条时间线进行一次max的计算,并且此时的数据选取逻辑是横向选取”30s“的原始数据。用下面的图进行解释此轮计算流程:在执行本轮计算时,需要对三条时间线都执行一次计算且得到三个数值。假设当前计算时间点为”09:00“,需要用每条时间线在"08:30 ~ 09:00"范围所有的指标值计算一个max值,并用该值作为此时间线在”09:00“时间点的结果值。

以此数据集与PromQL为例,最后的结果会存在三条时间线、123个数据点。


实际上,这种纵向计算模式对应了Prometheus中的 RangeVectorSelector

使用案例

此小结列举了几个PromQL的使用案例,同样以 instance 和 job 这两个Label为例进行分析。

  • 假设当前Metric表示请求的error数量
metric{instance="abc"}:instance为"abc"下所有job的error数量详情

sum(metric):求error数量的总和
sum(metirc) by (instance):对instance进行group by操作并求各类instance下的error数量和

delta(metric[2m]):每种instance和job下,计算2分钟时间区间的error数变化
rate(metric[2m]):每种instance和job下,计算2分钟时间区间的error增长率
  • 假设当前Metric表示cpu使用率
max_over_time(metric[2m]):每种instance和job下,计算2分钟时间区间内最大值
avg_over_time(metric[2m]):每种instance和job下,计算2分钟时间区间内平均使用率
stddev_over_time(metric[5m]):每种instance和job下,计算5分钟时间区间内的标准差

总结

本文首先介绍时序场景下的几个基础概念,然后着重对PromQL的执行过程与原理进行了详细介绍,最后列举了多个PromQL的使用案例并进行分析。相信在阅读完上文后,大家对PromQL的执行原理会有一个比较清晰的认识。

相关实践学习
容器服务Serverless版ACK Serverless 快速入门:在线魔方应用部署和监控
通过本实验,您将了解到容器服务Serverless版ACK Serverless 的基本产品能力,即可以实现快速部署一个在线魔方应用,并借助阿里云容器服务成熟的产品生态,实现在线应用的企业级监控,提升应用稳定性。
相关文章
|
27天前
|
监控
PromQL常见的使用场景
【10月更文挑战第14天】PromQL 的核心价值体现在时序数据的筛选与计算上。面对海量时序数据,PromQL 通过查询选择器实现高效过滤,满足特定监控图表渲染或告警规则处理的需求。
|
4月前
|
存储 Prometheus Cloud Native
SLS Prometheus存储问题之为什么SLS时序引擎最终选择了使用C++实现PromQL的部分算子
SLS Prometheus存储问题之为什么SLS时序引擎最终选择了使用C++实现PromQL的部分算子
|
6月前
|
存储 缓存 Java
Elasticsearch 8.X 聚合查询下的精度问题及其解决方案
Elasticsearch 8.X 聚合查询下的精度问题及其解决方案
180 0
|
6月前
|
Prometheus Cloud Native
「译文」如何使用 PromQL join 来更有效地查询大规模的 Prometheus 指标
「译文」如何使用 PromQL join 来更有效地查询大规模的 Prometheus 指标
|
存储 SQL 分布式计算
分布式图计算如何实现?带你一窥图计算执行计划
分布式图计算如何实现?带你一窥图计算执行计划
分布式图计算如何实现?带你一窥图计算执行计划
|
算法 数据挖掘 索引
白话Elasticsearch48-深入聚合数据分析之 Percentiles Aggregation-percentiles百分比算法以及网站访问时延统计及Percentiles优化
白话Elasticsearch48-深入聚合数据分析之 Percentiles Aggregation-percentiles百分比算法以及网站访问时延统计及Percentiles优化
120 0
|
分布式计算 算法 大数据
白话Elasticsearch45-深入聚合数据分析之易并行聚合算法,三角选择原则,近似聚合算法
白话Elasticsearch45-深入聚合数据分析之易并行聚合算法,三角选择原则,近似聚合算法
99 0
|
数据挖掘
白话Elasticsearch35-深入聚合数据分析之案例实战更多metrics用法:统计每种颜色电视最大最小价格
白话Elasticsearch35-深入聚合数据分析之案例实战更多metrics用法:统计每种颜色电视最大最小价格
92 0
|
存储 数据采集 Prometheus
PromQL 使用基础|学习笔记(四)
快速学习 PromQL 使用基础
242 0
PromQL 使用基础|学习笔记(四)
|
存储 Prometheus 监控
PromQL 使用基础|学习笔记(一)
快速学习 PromQL 使用基础
389 0
PromQL 使用基础|学习笔记(一)