prometheus的step,durations,rate interval,scrape interval对数据查询结果的影响
1、场景:在查询prometheus数据时出现很多诡异的现象
1、为什么同样的查询语句在不同的时间点查询,对过去某一时刻的数据展示却不一样
2、为什么有时候峰值在使用不同step,不同duration查询时,会不一样,甚至消失
3、为什么scrape interval变化了,会使某些规则的结果不准确
等等疑问
2、原理剖析:rate与irate,step,datapoint,scape_internal,instant vector selector,range vector selector
2-1、rate与irate的查询原理见之前博文:【博客486】prometheus-----rate,irate,increase的原理
2-2、step and datapoint and scape_internal:
data point:prometheus按照scrape_interval频率对metrics url进行抓取的原始数据
step:进行范围查询的时候,计算的步长是step这么长
scape_internal:prometheus按照scrape_interval频率对metrics url进行抓取
2-3、Instant vector selector与Range vector selector:
3、一条数据的查询结果受哪几个因素影响
3-1、影响因素:
1、scrape_interval
2、step
3、rate duration
4、query duration
3-2、rate查询语句格式:
rate(metrics_name[interval])
3-3、每个因素发挥的作用:
举例:查询最近3天x指标的增长速率:
curl ‘http://localhost:9090/api/v1/query_range?query=rate(x[10s])&start=2022-12-07T20:00:00.781Z&end=2022-12-10T20:00:00.781Z&step=30s’
1、scrape_interval:data point采样频率,决定了每个step计算值的时候,附近是哪些data point或者有没有data point
2、step:采样的步长,就是查最近3天的数据,对每step时长就计算一个速率值
3、rate duration:计算一个速率的值的时候的选择区间
4、query duration:查询的区间,就是最近3天
4、常见现象剖析
4-1、进行rate查询时,结果不同,甚至有时候严重失真
可能的错误结果1:展示时遗漏部分data point数据带来的错失部分峰值信息:
假设查询: rate(x[5s]),step为10s,查询过去一天的数据
结果分析: 那么rate在计算的时候会丢失一半的数据,两个分段之间的data point有一半没有被纳入计算。假设查询最近10s,然后rate每5s算一个点,但你每10s才收一个点来展示,展示漏了部分点,可能导致部分峰值信息被遗漏。
建议: 因此在使用rate()时,range duration得大于等于step。
可能的错误结果2:重复计算data point数据带来的部分假峰值信息:
假设查询: rate(x[5s]),scrape_interval为10s,step为5s,查询过去一天的数据
结果分析: 那么rate在计算的时候会重复计算一些数据,因为你step也是5s,那么rate每5s算一个点,且按照step来展示结果,但是你采集的时候10s才采集一个data point,那么其实多个step可能计算的时候取的是同一个data point。比如:采集点0s和10s,你按照step的5s来采集结果,那你在0s和5s时两个点都取了0s的结果,因为下一个data point在10s才有,可能导致部分峰值信息被遗漏。
建议: 因此在使用rate()时,range duration得大于等于scrape_interval和step。
4-2、同样的step,rate语句,time duration区间,但是对于历史时间点的结果有些变化或者消失了
假设查询: rate(x[5s]),scrape_interval为3s,step为5s,查询过去6小时的数据
重复执行多次,得到不同结果:查询今天0点到6点,和今天1点到7点这两段的数据,都包含了今天3点的数据结果,但是两次区间对今天3点附近的展示结果却不一样,可能按照0点到6点查询,3点的时候有峰值,按照1点到7点查询,则峰值不见卢,为什么对历史数据查询会不一样呢,历史数据不是既定事实了吗?
结果分析:因为你用不同的查询区间,那么step最近切出来start和end不一定一样,当时data point选择也不一样的。比如:
有data point:p1 p2 p3 p4 p5 p6
对应的值分别为:0,1000,0,1000,0
如果计算速率的时候,你start和end不定,查询区间如果起始是p1,数据点值选了0的几个,结果是:0
0,1000,0,1000,0
|----------|------------|
查询区间如果起始是p2,那么结果可能是选了两个1000的,(1000 + 1000)/2,结果:1000
0,1000,0,1000,0
-------|-----------|------------|
此时就会出现有的历史峰值存在,有的历史峰值不存在
建议:当你固定好时间区间的start和end,那么每次查询都是一样的
5、每个step如何取data point以及promql.LookbackDelta
-
在每一个时刻点上,使用该时刻点上(如果存在)的采样值
-
如果那个时间点上没有data point,则回溯到过去,使用最先遇到第一个采样值。
-
多个step可能回溯到相同的data point,比如:两个采样就能够跨好几个step(step很小的时候)。此时,就得到很多相同的采样值。
-
step向过去回溯时,最多回溯5min(promql.LookbackDelta = 5 * time.Minute),超过这个时长就不返回采样值啦。
6、step对谁起作用
答案:只对range query起作用。
-
查询instant query时,无需step。instant query求值时就使用一个时刻点。当前时刻点或自定义的时刻点(通过API查询时)。
-
查询range query时,step是有用的。先定出时刻点,然后,对于每一个时刻点,向过去回溯,使用最先遇到第一个采样值。
7、大跨度的时间查询如何保证峰值不丢失
解决方法:
当你进行大跨度的时间查询,比如:查询最近15天的cpu使用率,此时prometheus默认会以比较大的step去查询,那么就有部分峰值信息被遗漏了,此时可以通过手动指定较小的step进行查询,以避免遗漏部分峰值信息
注意点:
较小的step也就意味着较多的结果返回,如何进行处理,和对prometheus较大的查询压力,都是要考虑进去的
最佳实践
当查询一个信息的时候,要综合step,scape_internal,instant vector selector还是range vector selector,time duration,rate duration等因素进行综合考虑。切不可直接摘抄网上的查询语句进行查询,因为不同的业务场景下,区间和采集频率都不同