Prometheus分位值Sumary和Histogram数据详解

1 分位值基础概念

1.1 什么是分位值

分位值(也叫分位数、Quantile)是描述随机变量分布的特征统计量。将随机变量分布曲线与X轴围成的总面积做N等分,对应的N-1个分界点数值即为N分位值。

在数据分析与监控场景中,最常用的是四分位体系与高阶分位:

  • 25分位值(P25,下四分位):有25%的样本小于等于该值

  • 50分位值(P50,中位数):有50%的样本小于等于该值

  • 75分位值(P75,上四分位):有75%的样本小于等于该值

  • P90、P95、P99等高阶分位:常用于刻画系统长尾表现,对应90%、95%、99%的样本上限

1.2 分位值的业务意义

分位值的核心逻辑是:将所有样本从小到大排序,取排名处于N%位置的数值作为该分位结果。相比平均值,分位值能更真实地反映主体样本的实际水平,核心价值在于:

  • 平均值易被极端值“削峰填谷”,无法区分多数正常样本与少量异常长尾;高分位可以过滤极端异常,体现系统稳态下的性能表现

  • 可量化尾部风险:例如 P99 延迟代表 99% 的请求都能在该时间内完成,仅 1% 的请求超过该阈值,是服务 SLO(服务等级目标)的核心指标

  • 注意:高分位不适用于所有场景。在金融支付、强一致性交易等对可靠性要求 100% 的场景,不能忽略长尾异常,需关注全量数据与最大值

2 分位值的计算方法

2.1 基础计算逻辑

以N个有序样本为例,φ分位(0≤φ≤1)对应排名为φ×N的样本位置。当排名不是整数时,通用做法是通过线性插值计算最终结果,而非直接取邻近整数位置的原始值。Prometheus中histogram_quantile函数也采用桶内线性插值的估算逻辑。

2.2 手工计算示例

以数据集 [65, 23, 55, 78, 98, 54, 88, 90, 33, 48, 91, 84] 为例,计算四分位值:

  1. 数据排序
    从小到大排列为:23, 33, 48, 54, 55, 65, 78, 84, 88, 90, 91, 98,共12个样本,11个间隔。

  2. 四分位间隔
    每段四分位对应间隔数:11 ÷ 4 = 2.75

  3. 分位值插值计算

  • 25分位(P25)
    位置:第 1 + 2.75 = 3.75 个样本处,即第3个值(48)与第4个值(54)之间的0.75位置
    计算:48 + 0.75 × (54 - 48) = 52.5

  • 50分位(P50 / 中位数)
    位置:第 1 + 2.75 × 2 = 6.5 个样本处,即第6个值(65)与第7个值(78)之间的0.5位置
    计算:65 + 0.5 × (78 - 65) = 71.5
    也可通过偶数样本中位数公式直接计算:(65 + 78) ÷ 2 = 71.5

  • 75分位(P75)
    位置:第 1 + 2.75 × 3 = 9.25 个样本处,即第9个值(88)与第10个值(90)之间的0.25位置
    计算:88 + 0.25 × (90 - 88) = 88.5

2.3 练习

将1到100的整数序列做10等分,使用上述线性插值方法,计算P10(10分位)与P90(90分位)的数值。

总间隔 99,10 等分步长 9.9;P10 位置 10.9,结果 10.9;P90 位置 90.1,结果 90.1。

3 Histogram(直方图)数据类型

Histogram是Prometheus中用于统计数值分布的核心指标类型,本质是客户端分桶计数、服务端计算分位的累计直方图方案。

image

3.1 指标组成与格式

一个基础Histogram指标包含三类时间序列:

  1. _bucket 分桶计数序列
    每个bucket是一个累计计数器,标签le代表“小于等于该上边界”(less or equal, upper inclusive bound),即统计所有观测值 ≤ 该边界的样本总数。
    示例(TSDB压缩块大小):

     代表描述"tsdb_compaction_chunk_size_bytes"小于这个le的记录数位多少个:
     	prometheus_tsdb_compaction_chunk_size_bytes_bucket{le="32"} 0
     		tsdb压缩块大小小于32bytes的有0个。
     	prometheus_tsdb_compaction_chunk_size_bytes_bucket{le="48"} 806
     		tsdb压缩块大小小于48byte的有806个。
     	prometheus_tsdb_compaction_chunk_size_bytes_bucket{le="72"} 1683
     		tsdb压缩块大小小于72byte的有1683个。
     	prometheus_tsdb_compaction_chunk_size_bytes_bucket{le="108"} 2842
     		tsdb压缩块大小小于108byte的有2842个。
     	...
     	prometheus_tsdb_compaction_chunk_size_bytes_bucket{le="+Inf"} 6091
     		最后一定是一个"+Inf"(表示"正无穷")的记录,因为算分位值的时候要用到"+Inf"。
     		
     	值得注意的是,一个新的数据上报时,会把大于这个value的bucket全部"+1"。
     	
     Prometheus可以使用histogram数据类型可以采用分位值的方式随机采样短时间范围内的数据,从而及时发现问题,这需要配合histogram_quantile函数来使用。
    
    
     举个例子: HTTP请求的延迟柱状图(下面的"0.95"表示的是分位值,你可以根据需求自行修改即可。)
     histogram_quantile(0.95,sum(rate(prometheus_http_request_duration_seconds_bucket[1m])) by (le)) 
    
     histogram_quantile(0.95,sum(rate(prometheus_http_request_duration_seconds_bucket{handler="/api/v1/query"}[5m])) by (le)) 
    

    核心特性:每上报一个新样本,所有le值 ≥ 该样本值的bucket计数都会+1;+Inf(正无穷)桶为必选项,其值等价于总样本数。

  2. _sum 样本总和序列

    所有观测样本的数值总和。
    	代表记录的和,比如这个指标就是"tsdb_compaction_chunk_size_bytes"tsdb压缩块大小字节总和为"1.086535e+06"(将近1MB)。
    
  3. _count 样本总数序列

    观测样本的总数量。
      代表记录"tsdb_compaction_chunk_size_bytes"的数量和,就是一共"6091"次上报。
    

3.2 分位计算原理

Histogram本身不存储分位结果,需通过PromQL函数histogram_quantile(φ, buckets)基于分桶数据估算分位值:

  1. 先找到累计计数覆盖φ比例的目标桶;

  2. 假设样本在桶内呈均匀线性分布,通过线性插值计算分位对应数值;

  3. 结果为近似估算值,精度取决于bucket边界的疏密程度,桶越密集精度越高。

注意:bucket是累计计数器,计算时间窗口内的分位必须先通过rate()increase()获取窗口内的增量,否则结果无统计意义。

3.3 PromQL使用示例

# 1分钟窗口全量HTTP请求的P95延迟
histogram_quantile(0.95, sum(rate(prometheus_http_request_duration_seconds_bucket[1m])) by (le))

# 5分钟窗口指定接口的P95延迟
histogram_quantile(0.95, sum(rate(prometheus_http_request_duration_seconds_bucket{handler="/api/v1/query"}[5m])) by (le))

4 Summary(摘要)数据类型

Summary同样用于统计数值分布,核心特点是客户端预计算分位、服务端直接读取结果,分位计算在应用侧流式完成。

4.1 指标组成与格式

一个Summary指标包含三类时间序列:
image

 summary数据指标格式说明:
 	- XXX{...,quantile=XXX}:
 		使用quantile关键字定义具体的分位值。
 prometheus_target_interval_length_seconds{interval="15s",quantile="0.01"} 14.997928423
 	代表就是"1"分位值为"14.997928423"秒。
 	
 prometheus_target_interval_length_seconds{interval="15s",quantile="0.05"} 14.998842243
 	代表就是"5"分位值为"14.997928423"秒。
 	
 prometheus_target_interval_length_seconds{interval="15s",quantile="0.5"} 15.000025528
 	代表就是"50"分位值为"15.000025528"秒。
 	
 prometheus_target_interval_length_seconds{interval="15s",quantile="0.9"} 15.000811084
 	代表就是"90"分位值为"15.000811084"秒。
 	
 prometheus_target_interval_length_seconds{interval="15s",quantile="0.99"} 15.001590525
 	代表就是"99"分位值为"15.001590525"秒。
 	
 	
 	- XXX_sum:
 		代表记录的和,比如这个指标就是"target_interval(采集目标间隔时间)"消耗描述的和为"4785.00520029"。
 		
 	- XXX_count:
 		代表记录的数量和,一共上报了"319"次。

4.2 核心特性

  • 分位点必须在客户端埋点时预先定义,运行期无法新增未配置的分位;

  • 客户端通常采用流式算法(如GK算法)基于滑动窗口计算,单实例分位精度相对更高;

  • 不支持跨实例聚合:分位值不满足可加性,对多个实例的quantile结果做sum、avg等运算无统计意义,属于典型错误用法。

5 Histogram与Summary全面对比

对比维度 Histogram Summary
分位计算位置 服务端PromQL实时计算,依赖histogram_quantile 客户端SDK流式预计算,服务端直接读取
分位灵活性 支持0~1之间任意分位,查询时自由指定 仅支持埋点预设的分位点,运行期不可修改
多实例聚合 支持:先聚合bucket计数,再计算分位,结果有效 不支持:分位值无可加性,跨实例聚合结果错误
结果精度 桶内线性插值估算,精度由bucket边界密度决定 客户端流式算法输出,单实例精度相对更高
客户端开销 低,仅做分桶累加,逻辑简单 高,需维护流式分位算法与滑动窗口状态
服务端开销 高,分位计算为实时运算,高频查询建议配合记录规则优化 低,直接读取时序数值,无额外计算开销
时序数量 由bucket数量决定,分桶越多时序越多 由预定义分位点数量决定,时序数量可控
前置配置 需提前规划bucket边界 需提前定义分位点与滑动窗口大小

6 选型建议与常见误区

6.1 选型建议

  1. 优先选择 Histogram:多副本部署的服务、接口延迟统计、需要跨实例聚合、后续可能调整分位指标的场景,均推荐使用 Histogram,这也是 Prometheus 官方的主流推荐方案。

  2. 按需选择 Summary:单实例指标、无法提前预估数据范围、不需要跨实例聚合、追求单实例分位精度的场景(如 Go 运行时 GC 耗时等内置指标)可使用 Summary。

  3. Bucket 设置原则:优先使用指数分布的桶边界(官方默认延迟桶为指数分布),在数据集中的区域加密桶边界,长尾区域放宽桶宽度,平衡精度与时序数量。

6.2 常见使用误区

  1. Histogram 不套 rate() 直接计算分位
    bucket 是 Counter 类型,数值单调累计,直接计算得到的是服务启动至今的全量分布,而非指定时间窗口的分布,必须先通过 rate()/increase() 获取窗口增量。

  2. 对 Summary 的 quantile 做聚合
    分位数不满足可加性,avg()sum() 等聚合操作得到的结果不具备统计含义,属于典型错误用法。

  3. 混淆估算值与精确值
    Histogram 输出的分位是插值估算结果,并非原始样本的精确分位数;对精度要求极高的场景需合理加密 bucket。

  4. Bucket 设置不合理
    桶过宽会导致分位误差极大,桶过密会导致时序数量爆炸,存储与查询成本飙升,需结合业务数据分布调试。

posted @ 2026-08-07 15:31  kyle_7Qc  阅读(21)  评论(0)    收藏  举报