Prometheus高可用与联邦工程 - 第3节

3. 核心数据模型

Prometheus 的数据模型是其生态系统的基石。理解 Metric(指标)与 Label(标签)的设计哲学,是掌握采集作业平台架构的第一步。一个时间序列(Time Series)在 Prometheus 中由 指标名称 和一组 键值对标签 唯一标识。

3.1 Metric 命名规范与 Label 设计原则

Metric 名称用于描述被监控对象的通用语义,例如 http_requests_total 表示 HTTP 请求总数。Label 则用于区分同一 Metric 下的不同维度,例如 method="GET"、status="200"。

核心公式: 时间序列 = Metric 名称 + 标签集合(LabelSet)
元素 命名规范 示例 作用
Metric Name 符合正则 [a-zA-Z_:][a-zA-Z0-9_:]* node_cpu_seconds_total 描述被测量对象(如 CPU 使用时间)
Label Key 符合正则 [a-zA-Z_][a-zA-Z0-9_]* cpu, mode 定义维度(如 CPU 核心编号、运行模式)
Label Value 任意 Unicode 字符串 "0", "user" 维度具体取值
设计避坑: 避免在 Label Value 中存储高基数(High Cardinality)数据,如用户 ID、Email、请求 IP。高基数会导致 Prometheus 内存膨胀和存储性能急剧下降。一个 Metric 的 Label 组合基数建议控制在 10 万以内。

3.2 时间序列的底层数据结构

在 Prometheus 的 TSDB(时间序列数据库)中,每个时间序列由以下逻辑结构组成:

  • 标识符(Fingerprint): 对 Metric Name + Labels 进行哈希运算得到的 64 位唯一 ID,用于快速索引。
  • 样本数据(Sample): 由 timestamp(int64 毫秒时间戳)和 value(float64 浮点值)组成的键值对。
  • Chunk(数据块): 连续样本的压缩存储单元,默认包含约 120 个样本,采用 XOR 压缩算法(Facebook Gorilla 实现),大幅降低磁盘 I/O。
时间序列底层存储结构 Fingerprint (Hash ID) LabelSet (维度) Chunk 列表 (压缩块) Chunk 内部结构(XOR 压缩) 样本 1 (t1, v1) 样本 2 (t2, v2) 样本 3 (t3, v3) ... 样本 N 每个 Chunk 默认存储约 120 个样本,通过 XOR 算法压缩时间戳和值

4. 四种核心指标类型

Prometheus 客户端库提供了四种核心 Metric 类型。理解它们的适用场景与底层数据模型,是编写高效采集规则和告警表达式的关键。

4.1 Counter(计数器)

适用场景: 只增不减的累计值,如请求总数、任务完成数、错误发生次数。

  • 数据特性: 单调递增,重启时归零。
  • 典型操作: rate()(计算每秒增长率)、increase()(计算时间窗口内增量)。
  • 底层结构: 仅存储当前累计值,无额外状态。
# 示例:HTTP 请求总数
http_requests_total{method="POST", handler="/api/v1/order"} 1024

4.2 Gauge(仪表盘)

适用场景: 可增可减的瞬时值,如当前内存使用量、CPU 温度、并发连接数。

  • 数据特性: 上下波动,反映当前状态。
  • 典型操作: avg_over_time()、max()、min()。
  • 底层结构: 存储最新采样值,历史值由 TSDB 保留。
# 示例:当前内存使用字节数
node_memory_MemAvailable_bytes 8388608000

4.3 Histogram(直方图)

适用场景: 需要计算分位数(如 P99 延迟)或观察数据分布,如请求延迟、响应大小。

  • 数据特性: 自动将观测值落入预定义的桶(Bucket)中,同时提供总和与计数。
  • 典型操作: histogram_quantile() 计算分位数。
  • 底层结构: 生成多个时间序列:<basename>_bucket{le="<upper_bound>"}、<basename>_sum、<basename>_count。
# 示例:请求延迟直方图(单位:秒)
http_request_duration_seconds_bucket{le="0.1"} 50
http_request_duration_seconds_bucket{le="0.5"} 120
http_request_duration_seconds_bucket{le="1.0"} 150
http_request_duration_seconds_bucket{le="+Inf"} 200
http_request_duration_seconds_sum 85.3
http_request_duration_seconds_count 200

4.4 Summary(摘要)

适用场景: 需要直接获取预计算的分位数(如 P99),且对聚合精度要求较高,如服务端响应时间。

  • 数据特性: 在客户端侧直接计算分位数,并暴露给 Prometheus。
  • 典型操作: 直接查询 <basename>{quantile="0.99"}。
  • 底层结构: 生成多个时间序列:<basename>{quantile="<φ>"}、<basename>_sum、<basename>_count。
# 示例:请求延迟摘要(单位:秒)
http_request_duration_seconds{quantile="0.5"} 0.05
http_request_duration_seconds{quantile="0.9"} 0.3
http_request_duration_seconds{quantile="0.99"} 0.8
http_request_duration_seconds_sum 85.3
http_request_duration_seconds_count 200

4.5 四种指标类型对比

特性 Counter Gauge Histogram Summary
变化方向 只增不减 可增可减 累计计数 累计计数
典型场景 请求数、错误数 内存、温度、连接数 延迟分布、P99 预计算分位数
分位数计算 不支持 不支持 服务端计算 客户端预计算
聚合能力 可跨维度聚合 可跨维度聚合 可跨维度聚合 不可跨维度聚合
存储开销 低(1 个序列) 低(1 个序列) 高(N+2 个序列) 高(N+2 个序列)
选型建议: 对于需要计算分位数的延迟监控,如果客户端语言支持且不需要跨进程聚合,优先使用 Summary(性能更好);如果需要跨多个实例聚合计算全局分位数,则必须使用 Histogram。
四种核心指标类型选型决策流程 监控指标选型 是否只增不减? Counter 是否需要分位数? Gauge 是否需要跨进程聚合? Histogram Summary