3. Metric 标签基础:Prometheus 标签模型、标签的键值对结构、标签在时间序列中的唯一性作用

3.1 Prometheus 标签模型概述

在 Prometheus 生态中,标签(Label)是附加在时间序列上的键值对元数据,用于描述指标的维度特征。标签是区分不同时间序列的核心手段,也是实现租户隔离、聚合查询、告警路由的基础单元。

一个完整的 Prometheus 时间序列由以下三部分唯一确定:

  • Metric Name(指标名):如 http_requests_total,描述被测量对象。
  • Label Set(标签集):一组键值对,如 {method="GET", endpoint="/api/v1", tenant="acme"}。
  • Timestamp + Value:时间戳与对应的采样值。
核心原则:Metric Name + Label Set 共同构成时间序列的 身份标识(Identity)。只要标签集不同,即使指标名相同,也视为不同的时间序列。

3.2 标签的键值对结构

标签由 Label Key(标签键)和 Label Value(标签值)组成,遵循以下规则:

属性 规则 示例
Label Key 只能包含字母、数字、下划线,必须以字母或下划线开头 tenant_id、__name__、method
Label Value 任意 Unicode 字符串,可为空 "acme"、"GET"、""
保留前缀 以 __(双下划线)开头的 Key 为系统保留 __name__、__scheme__、__address__
最大数量 每个时间序列建议不超过 20 个标签 超过会导致性能下降

标签键值对在序列化时通常使用花括号包裹,例如:

http_requests_total{method="POST", endpoint="/api/order", tenant="tenant_a", status="200"}

3.3 标签在时间序列中的唯一性作用

标签是时间序列的 唯一性标识符。以下 SVG 展示了两个看似相同但实际不同的时间序列:

标签唯一性:相同指标名 + 不同标签集 = 不同时间序列 时间序列 A http_requests_total {method="GET", tenant="acme"} 值: 1024 @ t1 时间序列 B http_requests_total {method="POST", tenant="acme"} 值: 256 @ t1 标签不同 唯一性判定规则 • 指标名相同 + 标签集完全相同 = 同一个时间序列(覆盖旧值) • 指标名相同 + 标签集不同 = 不同的时间序列(独立存储) • 标签顺序不影响唯一性:{a="1",b="2"} 等价于 {b="2",a="1"}

3.4 标签基数与租户隔离的冲突点

标签在带来灵活性的同时,也引入了 基数爆炸(Cardinality Explosion) 风险。在租户隔离场景下,常见的标签治理冲突包括:

冲突类型 描述 示例
标签键冲突 不同团队使用相同 Key 表示不同含义 租户 A 用 env 表示“环境”,租户 B 用 env 表示“加密版本”
标签值泛滥 高基数标签导致时间序列数量失控 user_id、request_id、session_id 等唯一值标签
租户标签缺失 未携带租户标识,无法按租户隔离查询 指标只有 {method, endpoint},缺少 tenant 标签
标签命名不规范 大小写混用、特殊字符、命名风格不统一 TenantID vs tenant_id vs tenantId
⚠️ 租户隔离红线:所有上报的指标 必须 携带统一的租户标签(如 tenant_id),且该标签的值必须来自认证鉴权系统,禁止客户端自行伪造。缺少租户标签的指标应被拒绝或丢弃。

3.5 标签治理最佳实践

在租户隔离的 Metric 体系中,标签治理应遵循以下原则:

  1. 统一标签命名规范:使用小写字母 + 下划线,如 tenant_id、service_name、region。
  2. 限制标签基数:每个标签的取值数量建议不超过 1000,避免使用 user_id、ip 等高基数标签。
  3. 强制租户标签:在采集侧或代理侧注入 tenant_id 标签,确保每条时间序列都可归属到具体租户。
  4. 标签白名单机制:只允许预定义的标签键通过,拒绝未知标签。
  5. 标签值长度控制:标签值不宜过长,建议不超过 128 字符。

以下 SVG 展示了从指标采集到存储的标签治理流程:

标签治理流程:从采集到存储 原始指标 {method, endpoint} 标签注入 + tenant_id, service 标签校验 白名单 / 基数检查 TSDB 存储 拒绝 / 丢弃 不合规标签 校验失败
💡 实践建议:在 Prometheus 的 relabel_configs 或代理层(如 OpenTelemetry Collector)中实现标签注入与校验,避免在应用代码中手动处理租户标签,降低耦合度。