关于rrdtool graph设置--step 300后图表宽度影响95百分位数计算结果的技术问询
背景与问题现象
我手里有个存了好几个月5分钟间隔PDP数据的RRD文件,平时用rrdtool自动选RRA绘图完全够用,但涉及到图例里的95百分位数就麻烦了——这玩意儿必须用精确的5分钟原始数据算,从聚合数据里算百分位数根本就是错得离谱。
本来我以为用--step 300参数就能强制拉取原始5分钟数据来计算,结果发现了个诡异的情况:同样的1个月时间范围,同样加了--step 300,图表宽度不同,算出来的百分位数(还有最大值这类指标)居然不一样:
- 把图表宽度设成800px时,结果明显不对;
- 宽度拉到8000px时,数值就完全正确了,和我用
rrdtool fetch手动拉数据算出来的结果一模一样。
相关配置与命令
我创建RRD时的关键参数:
'-s', '300', ...
RRD里的RRA配置如下:
"RRA:AVERAGE:0.5:1:53568", # 5分钟间隔,存6个月的PDP数据 "RRA:AVERAGE:0.5:12:8904", # 1小时聚合间隔,存1年数据 "RRA:AVERAGE:0.5:288:730", # 1天聚合间隔,存2年数据 "RRA:AVERAGE:0.5:2016:520", # 1周聚合间隔,存10年数据 "RRA:MAX:0.5:1:600", # 5分钟间隔的MAX值,仅存2天数据 "RRA:MAX:0.5:12:8904", # 1小时聚合的MAX值,存1年数据 "RRA:MAX:0.5:288:730", # 1天聚合的MAX值,存2年数据 "RRA:MAX:0.5:2016:520", # 1周聚合的MAX值,存10年数据
绘图时的核心命令片段:
... --step 300 ... "VDEF:perca=a,95,PERCENT", ...
问题根源
这其实是RRDTool的自动降采样逻辑在搞鬼。虽然你指定了--step 300,但RRDTool会默认根据图表的像素宽度来调整实际使用的数据点数量——说白了就是如果图表太窄,它会把多个5分钟的原始数据点合并成一个像素对应的聚合值,然后用这些聚合后的数值来计算VDEF的百分位数,结果自然就跑偏了。
举个例子:1个月大概有4320个5分钟数据点(30天×24小时×12个5分钟段),如果图表宽度是800px,RRDTool会把每5-6个原始点合并成一个(4320÷800≈5.4),这时候用的根本不是原始的300秒数据,而是聚合后的数值,算出来的百分位数肯定不准。而宽度设成8000px时,每个像素对应不到1个原始点,RRDTool才会老老实实使用全部原始300秒数据来计算。
另外还要注意:你那个5分钟间隔的MAX RRA只存了2天的数据(600个点),要算1个月的百分位数,只能用那个存了6个月的5分钟AVERAGE RRA,不然数据范围根本覆盖不了。
解决方案
要彻底解决这个问题,就得强制RRDTool使用存储原始5分钟数据的RRA,不让它自动做降采样,具体有两种靠谱的方式:
- 指定RRA索引强制拉取原始数据
在绘图命令里加上--rra-index 0(对应你那个存了6个月的5分钟AVERAGE RRA,也就是RRA列表里的第一个),这样不管图表宽度设置成多少,RRDTool都会直接从这个RRA里取原始的300秒数据来计算百分位数。
调整后的绘图命令片段大概是这样:
... --step 300 --rra-index 0 ... "VDEF:perca=a,95,PERCENT", ...
- 禁用自动降采样的额外配置
如果你不想指定RRA索引,也可以尝试在命令里加上--full-scan参数,让RRDTool扫描所有可用的RRA来匹配你指定的--step,不过这种方式不如直接指定RRA索引来得稳妥。
总结
核心问题就是RRDTool默认会根据图表像素自动降采样,哪怕你指定了--step也没用。只要强制它使用存储原始5分钟数据的RRA,就能保证百分位数计算基于精确的原始数据,不会再随图表宽度变化而出错了。
内容的提问来源于stack exchange,提问作者powo

