Prometheus采集作业平台架构设计与核心原理精讲 - 第3节
3. 核心数据模型:Metric与Label设计原理
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。
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。