3. Prometheus 数据模型:理解 Metric、Label、Sample、Time Series,为聚合查询打基础
在排查误差预算台账数据偏差时,我们面对的是海量的时间序列数据。要精准地使用 PromQL 进行聚合查询,首先必须理解 Prometheus 底层的数据模型。这个模型定义了数据如何被采集、存储和标识,是编写任何有效查询的基石。
3.1 核心概念:四大要素
Prometheus 的数据模型由四个核心要素构成,它们共同定义了一个唯一的时间序列。
| 要素 | 定义 | 在误差预算场景中的示例 |
|---|---|---|
| Metric(指标) | 被监控的特定度量项的名称,描述“测量什么”。 | http_request_duration_seconds(HTTP 请求耗时) |
| Label(标签) | 键值对,用于对指标进行多维度的特征描述,描述“如何测量”。 | service="checkout", status="500", method="POST" |
| Sample(样本) | 一个具体的数据点,包含一个时间戳和一个值。 | t=1700000000, v=0.95(在时间 t 时,P95 延迟为 0.95 秒) |
| Time Series(时间序列) | 由 Metric 名称和一组唯一 Label 组合定义的、按时间排序的样本流。 | http_request_duration_seconds{service="checkout", status="200"} 的所有历史样本。 |
3.2 数据模型结构图
下图直观地展示了 Metric、Label、Sample 和 Time Series 之间的关系。一个 Metric 名称加上一组唯一的 Label 组合,就定义了一个 Time Series,而 Time Series 则是由一系列按时间排序的 Sample 组成的。
3.3 深入理解各要素
3.3.1 Metric(指标)
Metric 名称通常反映被监控对象的业务或技术含义。命名遵循 a-z, 0-9, 下划线和冒号。在误差预算场景中,常见的 Metric 包括:
slo_ratio:服务等级目标达成率。error_budget_burn_rate:错误预算消耗速率。http_requests_total:HTTP 请求总数。
3.3.2 Label(标签)
Label 是 Prometheus 数据模型实现多维可观测性的核心。通过不同的 Label 组合,我们可以从不同维度切分数据。在排查偏差时,错误的 Label 值或缺失的 Label 是常见的数据源。
{__name__="your_metric"} 查询所有 Series,确认 Label 的键和值是否正确。
3.3.3 Sample(样本)
每个样本由两部分组成:
- Timestamp(时间戳):毫秒精度,表示数据采集的时刻。
- Value(值):一个 64 位浮点数,代表该时刻的度量值。
在 PromQL 中,我们通过 @ 修饰符或范围向量选择器来操作样本的时间维度。
3.3.4 Time Series(时间序列)
一个 Time Series 由 Metric 名称 + 一组唯一的 Label 组合 唯一标识。例如:
http_requests_total{job="api-server", instance="10.0.0.1:9090", method="GET", status="200"}
这是一个独立的 Time Series。如果 status 变为 500,则是一个全新的 Time Series。聚合查询(如 sum by (service))的作用,就是将多个 Time Series 按照指定的 Label 维度进行合并计算。
3.4 数据模型与聚合查询的关系
理解数据模型是编写正确 PromQL 的前提。下表总结了数据模型要素与聚合查询操作之间的对应关系:
| 数据模型要素 | 在聚合查询中的作用 | 常见错误 |
|---|---|---|
| Metric | 指定聚合操作的目标数据集。 | Metric 名称拼写错误,导致查询不到数据。 |
| Label | 定义聚合的维度(by 子句)或过滤条件({} 选择器)。 |
在 by 子句中遗漏了关键 Label,导致结果粒度太粗;或使用了不存在的 Label 值。 |
| Sample | 提供参与聚合计算的原始数值。 | 忽略了样本的时间范围(如 [5m]),导致计算了错误时间窗口的数据。 |
| Time Series | 聚合操作的基本单元。聚合函数将一组 Time Series 合并为一个或一组新的 Time Series。 | 未意识到高基数 Label(如 user_id)会导致大量 Time Series,使聚合查询性能下降或结果不准确。 |
user_id、request_id 等具有极高基数的值作为 Label。这会导致 Time Series 数量爆炸,不仅影响 Prometheus 性能,也会使聚合查询结果难以解读。应使用 service、status、slo_name 等低基数 Label。
3.5 数据模型在偏差排查中的实际应用
假设我们有一个误差预算指标 error_budget_remaining,其 Label 包括 service、slo_name 和 window。当我们发现某个服务的预算消耗异常时,排查路径如下:
- 确认 Metric 存在: 查询
{__name__="error_budget_remaining"},确认数据正在被采集。 - 检查 Label 维度: 查看返回的 Time Series,确认
service="checkout"的 Label 值是否正确,是否存在拼写错误(如service="checkout "带空格)。 - 分析样本值: 使用
error_budget_remaining{service="checkout"}[1h]查看过去一小时的样本值变化,确认是突然下降还是持续消耗。 - 聚合验证: 使用
sum by (service) (error_budget_remaining)查看所有服务的总预算,与单个服务对比,确认偏差是否由数据聚合方式引起。
通过以上步骤,我们可以系统性地定位数据偏差的根因,是数据采集问题、Label 配置问题,还是 PromQL 查询逻辑问题。