Prometheus 的 histogram_quantile 有多准?桶该怎么划分?数据超出最大桶时会怎样?rate 的窗口怎么影响分位数?桶越多序列数增长多快?这篇用 Prometheus 3.15.0 和同一批 10 万个样本逐项量出来。
真实分位数(ms):p50 = 20.1, p90 = 58.3, p99 = 524.7, p99.9 = 961.9 桶划分 | 有限桶个数 | p50 估计(相对误差) | p90 估计(相对误差) | p99 估计(相对误差) | p99.9 估计(相对误差) -----------------------------------------+-------+--------------+--------------+--------------+--------------- prometheus_client 默认(×1000) | 14 | 21.2(+5%) | 61.5(+5%) | 523.7(-0%) | 952.2(-1%) 线性,每 50 ms 一个 | 20 | 28.9(+43%) | 66.9(+15%) | 525.3(+0%) | 956.5(-1%) 指数,×2(5 到 1280) | 9 | 20.2(+0%) | 67.0(+15%) | 400.8(-24%) | 1196.8(+24%) 指数,×1.3(5 到约 1000) | 21 | 20.3(+1%) | 59.5(+2%) | 489.8(-7%) | 950.2(-1%) 只有两个桶:100、1000 | 2 | 51.7(+157%) | 93.0(+60%) | 723.2(+38%) | 972.3(+1%) 围绕慢请求加密:10、20、40、80、200、400、600、800、1000 | 9 | 20.2(+0%) | 67.0(+15%) | 455.6(-13%) | 952.3(-1%) 桶越宽,线性插值的误差越大;最大误差出现在分位数落进宽桶的时候。桶边界要覆盖要关心的分位数和阈值附近(例如 SLO 的 500 ms),并不是桶越多越好
误差最大出现在分位数落进宽桶时;桶的位置比数量重要。
数据 | p50 估计(ms) | p99 估计(ms) | 用 sum / count 算的平均值(ms) -------------------+------------+------------+------------------------ (a)全部 3000~9000 ms | 1000.0 | 1000.0 | 5996.7 (b)全部恰好 100 ms | 75.0 | 99.5 | 100.0 (c)全部 100.001 ms | 175.0 | 248.5 | 100.0 超出最大有限桶的数据都进了 +Inf 桶,histogram_quantile 在落进 +Inf 桶时只能返回最大有限桶的上界(这里 1000),平均值(sum / count)才反映真实水平;桶边界是“小于等于”,恰好 100 ms 的请求进 le=100 的桶,估计值是这个桶 (50, 100] 内线性插值的位置(p50 = 75、p99 = 99.5),不是 100 本身;100.001 ms 的请求落进下一个桶 (100, 250]
超出最大有限桶的数据只能返回最大有限桶的上界;恰好落在边界上的值归入“小于等于”的桶。
查询时刻(服务第 30 秒起变慢) | rate 窗口 W | p50 估计(ms) | 窗口内真实 p50(ms) | p99 估计(ms) | 窗口内真实 p99(ms) | 窗口内慢阶段请求的比例 ------------------+-----------+------------+---------------+------------+---------------+------------ 第 50 秒 | 10 s | 175.0 | 200.0 | 248.5 | 200.0 | 100% 第 50 秒 | 30 s | 141.2 | 200.0 | 247.8 | 200.0 | 67% 第 50 秒 | 60 s | 9.4 | 10.0 | 246.5 | 200.0 | 40% 第 60 秒 | 10 s | 175.0 | 200.0 | 248.5 | 200.0 | 100% 第 60 秒 | 30 s | 175.0 | 200.0 | 248.5 | 200.0 | 100% 第 60 秒 | 60 s | 110.0 | 105.0 | 247.2 | 200.0 | 50% 窗口里同时有快慢两个阶段时,p50 由占多数的阶段决定:第 50 秒时慢阶段只占 W=60 s 窗口的一部分(见表中最后一列),p50 还是快阶段的值,而 W=10 s 的窗口全是慢阶段;p99 只要慢阶段占比不低于 1% 就落在慢阶段的桶里,所以几个窗口给出几乎一样的值;p99 的估计比真实值(200)高,是因为落进 (100, 250] 这个桶之后在桶内做线性插值,与窗口无关
窗口里同时有两个阶段时,p50 由占多数的阶段决定;p99 只要慢阶段占比不低于 1% 就落在慢阶段。
有限桶个数 | 标签组合数 | _bucket 序列数 | 这个 histogram 的总序列数(含 _sum、_count) | 平均每个标签组合的序列数
------+-------+-------------+-----------------------------------+-------------
5 | 150 | 900 | 1350 | 9
14 | 150 | 2250 | 2700 | 18
20 | 150 | 3150 | 3600 | 24
每个标签组合的序列数 = 有限桶个数 + 1(+Inf 桶)+ 2(_sum 和 _count)+ 1(prometheus_client 额外暴露的 _created),数字与上表一致;桶越多、标签组合越多,序列数相乘增长
ERRORS {}每个标签组合的序列数随桶数线性增长,标签组合数乘进去。