Prometheus High Cardinality(高基数)问题完全指南

TL;DR

  • 高基数(High Cardinality)问题的核心不是 sample 数量大,而是 Time Series(时间序列)组合数失控
  • 判断一个 label 是否适合进入 Prometheus,关键不在于"值很多",而在于它是否 有上界、可估算、可聚合
  • request_idtrace_idsession_iduser_idpod_uidcontainer_id 这类 label 往往不是"高基",而是接近无上界,应优先排除在指标体系之外。
  • 排查高基数时,不能只看 Head Series,还要同时看 Series Churn,即单位时间新增和淘汰的时序速率。
  • 在 Kubernetes / Agent 场景中,nodenamespacepodagent_id 往往属于高基但可控;请求级、瞬态实例级 label 才是更常见的风险源。
  • Prometheus 适合聚合统计,不适合明细检索。需要保留请求明细、用户明细或事件明细时,应优先考虑日志、Tracing 或 OLAP 链路。
  • 一条经验结论可以直接记住:凡是可能"按请求生成新值"的 label,默认都不应该进入 Prometheus。

Prometheus 的高基数(High Cardinality)问题,是很多团队在监控系统规模扩大后最常遇到的稳定性问题之一。

很多 Prometheus OOM、查询变慢、监控系统不稳定的根因,并不是采样频率,而是 Time Series 组合数失控。

本文从 TSDB 原理出发,系统解释 High Cardinality 的形成机制,并给出 Kubernetes 与 Agent 场景下的工程治理方法。


问题定义:什么是高基数

在 Prometheus 中,一条 Time Series(时间序列) 由指标名和一组标签唯一确定:

text 复制代码
series = metric_name + label_set

例如:

text 复制代码
http_requests_total{method="GET",status="200",instance="api-1"}

只要 label_set 中任意一个值不同,就会形成新的 Time Series。

这里的关键概念是 Label Cardinality(标签基数)

它表示某个 label 的不同取值数量。

例如:

text 复制代码
method   = {GET, POST}      -> cardinality = 2
status   = {200, 404, 500}  -> cardinality = 3
instance = 1000 台实例       -> cardinality = 1000

单个 label 的基数高,并不一定构成问题。

真正的风险来自多个维度叠加后的乘法效应,也就是 Series Explosion(时序爆炸)

如果一个指标同时带有以下标签:

text 复制代码
method   = 2
status   = 5
pod      = 3000
instance = 1000
user_id  = 1000000

那么理论上的时序数量大致为:

text 复制代码
2 x 5 x 3000 x 1000 x 1000000

这已经超出任何常规 Prometheus 实例可以承载的范围。

Series Explosion:一个更贴近工程现场的计算示例

假设某个 Kubernetes 集群中有一组对外 API 服务,规模如下:

  • 200 个 Pod
  • 每个 Pod 暴露 1 组 HTTP 请求指标
  • method 维度取值 4
  • status 维度取值 8
  • route 模板 60

如果指标设计是合理的:

text 复制代码
http_requests_total{method, status, route, pod}

那么这一类指标的时序规模大致为:

text 复制代码
200 x 4 x 8 x 60 = 384000 series

这个数量不算低,但它仍然属于可估算、可拆分、可治理的范围。

如果同一类指标额外引入了 user_id,并且活跃用户规模按 500000 估算,那么规模会变成:

text 复制代码
200 x 4 x 8 x 60 x 500000 = 192000000000 series

这里的问题不在于 user_id 这个字段"多了一个",而在于它把一个原本可聚合的问题,变成了一个几乎无上界的明细建模问题。

因此,高基数问题不应该理解为"标签多了几个",而应理解为:
某个本该用于聚合统计的指标,被引入了不适合做聚合的维度。


原理:Series、Label、Inverted Index 与 Series Churn 的关系

Time Series 是如何写入 TSDB 的

Prometheus 的 TSDB(时序数据库)在接收 sample 时,核心流程可以简化为:

text 复制代码
sample
  -> normalize labels
  -> hash(label set)
  -> lookup or create series
  -> append sample to chunk
  -> update index metadata

也可以用更接近内部结构的方式表示为:

text 复制代码
+--------+    +------------------+    +-----------------+    +---------------+    +--------------+    +-----------------------+
| sample | -> | normalize labels | -> | hash(label set) | -> | create series | -> | append chunk | -> | update inverted index |
+--------+    +------------------+    +-----------------+    +---------------+    +--------------+    +-----------------------+

如果按时序写入路径展开,也可以表示为:

text 复制代码
sample
  │
normalize labels
  │
hash(label set)
  │
lookup / create series
  │
append chunk
  │
update inverted index

如果 sample 命中了已有的 Time Series,Prometheus 主要做的是追加写入。

如果出现了新的 label_set,Prometheus 就必须创建新的 series 元数据,并更新索引结构。

Prometheus 的资源消耗主要来自 Time Series 数量和 Series Churn,而不是 sample 数量。

因此,Prometheus 的成本不只由 sample 数决定,还直接取决于:

  • 当前活跃 Time Series 数量
  • 新建 Time Series 的频率
  • label 组合的复杂度

Inverted Index 为什么会被高基数放大

Prometheus 查询依赖 Inverted Index(倒排索引)

可以粗略理解为:

text 复制代码
method="GET"  -> series1, series2, series3
status="500"  -> series2, series8
pod="api-1"   -> series1, series2

查询时,Prometheus 需要根据多个 label matcher 在这些 posting list 上做过滤和求交。

这意味着高基数会同时放大两类成本:

  • 写入时:更多 series 元数据、更多 label 存储、更多索引项
  • 查询时:更大的 posting list、更高的求交和扫描成本

很多团队只关注"磁盘能不能放下",但 Prometheus 更先遇到的问题通常是:

  • Head Block 元数据驻留内存上升
  • 倒排索引维护成本增加
  • 查询延迟变大
  • CPU 被查询和压缩任务拉高

Head Series 与 Series Churn 要分开看

在排查时,至少要区分两个概念:

  • Head Series:当前活跃的 Time Series 数量
  • Series Churn:单位时间内新建和淘汰的 Time Series 速率

两者不是一回事。

如果系统的 Head Series 很高,说明当前常驻的时序很多。

如果系统的 Series Churn 很高,即便总量没有立刻失控,也可能因为频繁创建和淘汰时序而产生额外压力。

例如下面两种情况:

  1. 资源级 label 很多,但系统规模稳定

    结果往往是高基但可控。

  2. 每个请求都带 request_idtrace_id

    结果往往是持续创建新 series,形成明显的 churn。

在工程上,第二类问题通常更危险,因为它往往意味着基数没有天然上界。


危害:高基数为什么会导致内存、索引、查询和 OOM 问题

高基数问题在 Prometheus 中通常沿着下面这条链路放大:

  1. 新的 label 组合不断进入系统
  2. Time Series 数量上升
  3. Head Series 与索引元数据占用更多内存
  4. 查询扫描范围扩大,CPU 与延迟上升
  5. 在持续增长或 churn 很高时,实例变得不稳定,甚至 OOM

具体表现通常包括:

  • prometheus_tsdb_head_series 持续上涨
  • prometheus_tsdb_symbol_table_size_bytes 增长明显
  • process_resident_memory_bytesgo_memstats_heap_alloc_bytes 上升
  • 查询变慢,Grafana dashboard 响应时间拉长
  • 抓取、压缩、规则评估相互竞争资源

需要强调的是,Prometheus 的问题并不总是因为"采样太密"。

在很多实际场景里,真正的瓶颈来自:

  • 标签组合过多
  • 新建时序过快
  • 把明细维度误放进了聚合系统

官方建议与工程理解

Prometheus 官方长期建议避免把高基数字段直接作为 label。相关文档可直接参考:

工程上更值得关注的不是"背结论",而是理解这些建议背后的系统成本。

这条建议在工程上应理解为两层含义:

第一层:不要把无上界输入直接映射为 label

典型风险字段包括:

  • request_id
  • trace_id
  • span_id
  • session_id
  • user_id
  • device_id
  • order_id
  • container_id
  • pod_uid

这些字段的问题不只是"值多",而是:

  • 取值往往来自请求或运行时对象
  • 无法提前估算真实上界
  • 很容易持续产生新值
  • 对 Prometheus 的聚合分析帮助有限

第二层:高基数不等于一定错误

以下标签在很多系统里本身也是高基数:

  • instance
  • node
  • pod
  • namespace
  • agent_id

但它们通常具备几个特征:

  • 与基础设施规模相关
  • 具备可估算上界
  • 在定位问题时有明确价值

因此,真正需要区分的是:

  • 有上界的高基
  • 无上界的高基

前者未必错误,后者才是 Prometheus 体系里更常见的系统性风险。


哪些 label 可以接受,哪些必须避免

下面这张表更适合作为工程决策表,而不是"绝对规则表"。

label 类型 典型例子 是否建议进入 Prometheus 原因 更合适的替代方案
资源级 label instancenamespacepodnodeagent_id 通常建议 与集群或节点规模相关,通常存在可估算上界,且对定位问题有价值 保留,但控制粒度;必要时按集群/业务拆分采集
业务聚合级 label methodstatusroute 建议 基数通常较低,天然适合聚合统计和告警 继续保留,并使用模板化 route、状态码分组
请求级 label request_idtrace_idspan_id 不建议 随请求持续生成新值,Series Churn 高,几乎没有可控上界 放入 Tracing、日志或事件流
用户级 label user_iddevice_idsession_id 不建议 取值空间大且来自业务明细,不适合聚合监控 用用户分层、租户分组、region 等聚合维度替代
运行时实例级 label container_idpod_uid 通常不建议 生命周期短、变化频繁,容易造成高 churn,且往往与 pod / container 名称重复 保留 podnamespacecontainer 等稳定维度即可

这张表背后的判断标准只有三个:

  • 是否有明确上界
  • 是否能服务于聚合统计
  • 是否会因请求或运行时对象变化而持续产生新值

检测方法:PromQL、Dashboard、TopN 与 Churn 观察

高基数问题不适合等到 OOM 再排查。

更稳妥的做法是把它作为常规容量治理的一部分。

1. 先看总量:Head Series

promql 复制代码
prometheus_tsdb_head_series

这条指标反映当前活跃时序规模。

它不是根因定位工具,但可以帮助判断系统是否已经逼近容量边界。

建议同时观察:

promql 复制代码
prometheus_tsdb_head_chunks
prometheus_tsdb_symbol_table_size_bytes
process_resident_memory_bytes

如果这些指标同步上升,通常说明:

  • 活跃时序在增长
  • 标签元数据和索引负担在变重
  • 实例内存压力正在增加

2. 再看增速:新建 Series 速率

promql 复制代码
rate(prometheus_tsdb_head_series_created_total[5m])

如果该值在没有业务扩容、没有大规模变更的情况下持续偏高,需要重点怀疑:

  • 引入了无上界 label
  • 某类 exporter 输出了异常维度
  • 某个 label 的取值空间发生了非预期膨胀

对应地,也建议同时看:

promql 复制代码
rate(prometheus_tsdb_head_series_removed_total[5m])

如果创建和移除都很高,说明存在明显的 Series Churn。

如果创建高、移除低,说明时序总量还在积累。


3. 定位问题指标:TopN Series

在很多环境里,第一步先做 TopN 排查就足够有效:

promql 复制代码
topk(20, count by (__name__)({__name__=~".+"}))

这条查询适合快速找出"当前时序规模最大的指标名"。

如果环境中支持额外的 cardinality 分析工具,还应进一步展开:

  • 哪些 label 贡献了最多组合
  • 哪些指标在过去一段时间内 churn 明显升高
  • 哪些 job / target 带来了新时序增长

4. 检查某个维度的 Cardinality

例如查看 instance 数量:

promql 复制代码
count(count by (instance) (up))

查看某个业务指标下 pod 维度规模:

promql 复制代码
count(count by (pod) (http_requests_total))

查看 route 维度规模:

promql 复制代码
count(count by (route) (http_request_duration_seconds_count))

这些查询并不复杂,但足以帮助判断:

  • 某个 label 是否超出系统规模预期
  • 某个业务是否引入了不合理维度

5. 建立专门的 Cardinality Dashboard

建议为 Prometheus 实例单独建设一个 dashboard,最少包含:

  • Head Series
  • Series Created Rate
  • Series Removed Rate
  • Symbol Table Size
  • RSS / Heap
  • 慢查询趋势

如果系统规模较大,还建议按以下维度拆开观察:

  • 按 job 的抓取规模
  • 按业务域的指标数量
  • 按集群或环境的 series 分布

高基数问题一旦走到 OOM 阶段,处理成本就已经偏高。

更合理的方式是在它还只是"曲线开始变陡"时发现它。

一个更适合落地执行的高基数排查路径如下:

text 复制代码
发现监控异常
      │
Head Series 是否异常
      │
查看 Series Created Rate
      │
定位 TopN 指标
      │
检查 label cardinality
      │
确认是否存在 request_id / user_id / container_id 等无界 label

常见高基数事故案例

案例一:把 request_id 直接打进请求指标

典型形式:

text 复制代码
api_request_total{method="GET",status="500",request_id="req-xxx"}

事故模式通常是:

  • 业务请求量本身不算异常
  • Prometheus 抓取仍然成功
  • Head SeriesSeries Created Rate 持续上升
  • 最终内存压力和查询性能同时恶化

这类问题的根因通常不是"流量太大",而是指标把每个请求都建模成了新的 Time Series。

案例二:把原始 URL 当作 path label

典型形式:

text 复制代码
http_request_duration_seconds{path="/api/orders/123456"}

如果 URL 中包含订单号、用户 ID、文档 ID 或其他业务主键,path 的 cardinality 会随业务数据规模同步增长。

这类事故的典型特征是:

  • 整体 QPS 没明显变化
  • 但某几个业务接口的指标规模异常大
  • route 模板本可稳定聚合,却被原始路径替代

案例三:把 pod_uid / container_id 这类瞬态实例 ID 暴露为 label

典型形式:

text 复制代码
runtime_metric{pod_uid="...",container_id="..."}

这类问题常见于 Kubernetes 生态中的自定义 exporter 或中间层组件。

问题不一定会立刻表现为超大 Head Series,但往往会表现为:

  • 实例滚动升级后 Series Churn 明显升高
  • Prometheus 内存和 WAL 压力持续波动
  • 相同语义的资源被重复编码为不同的瞬态 ID

这些案例的共性都很明确:
Prometheus 被拿来承接明细主键或瞬态对象,而不是承接聚合维度。


Kubernetes / Agent 场景分析

Kubernetes 场景里,高基数判断经常被简单化为"pod 多,所以天然会炸"。

这个判断不准确。

为什么 agent_id 往往属于"高基但可控"

在 Node Agent、日志 Agent、eBPF Agent、宿主机采集器这类系统里,agent_id 往往对应一台机器、一个节点或一个固定部署单元。

例如:

text 复制代码
agent_metric{agent_id="node-172-20-10-12"}

它的基数可能很高,但通常仍然可接受,因为:

  • 基数和节点规模直接相关
  • 上界可以通过集群容量规划估算
  • 对故障定位和实例级观测有实际价值

这属于典型的有上界的高基


为什么 pod / namespace / node 通常可接受

这类 label 的共同点是:

  • 来自稳定的资源模型
  • 与 Kubernetes 对象层级一致
  • 在调度、容量和故障定位中具有直接意义

例如:

text 复制代码
container_cpu_usage_seconds_total{namespace="prod",pod="api-7d8b9",node="worker-12"}

这里的 namespacepodnode 虽然可能数量不少,但通常仍是合理维度。

因为它们反映的是资源实体,而不是请求明细。


为什么 pod_uid / container_id / request_id / trace_id 危险

这些 label 的问题在于它们往往同时具备以下属性:

  • 生命周期短
  • 变化频繁
  • 与请求或瞬态实例绑定
  • 容易产生新的唯一值

例如:

text 复制代码
request_total{pod_uid="...", container_id="...", request_id="...", trace_id="..."}

这类指标把基础设施层和请求层的明细维度混在了一起。

它们通常会带来两个后果:

  • Head Series 增长失控
  • Series Churn 异常升高

这是比"pod 数量多"更常见、也更危险的问题。


高基不等于一定错误,关键在于是否有上界

在 Kubernetes / Agent 场景中,最实用的判断方式不是问"这个 label 高不高",而是问:

  1. 它是否与资源规模直接相关?
  2. 它能否提前估算上界?
  3. 它是否有稳定的聚合价值?
  4. 它是否会按请求或实例重建而不断产生新值?

如果前 3 个答案偏正面,第 4 个答案是否定的,那么即使它是高基,也通常是可接受的。

反之,即便当前数量看起来不大,也可能是一个未来会失控的风险源。


治理方法:指标设计、Label 收敛、采集侧处理与架构隔离

高基数治理不应停留在"出事后删标签"。

更稳妥的做法是从设计、采集、运行和架构几个层面同时建立边界。

1. 指标设计:先判断它是不是一个聚合维度

Prometheus 适合描述:

  • 某类请求的总量
  • 某类错误的比例
  • 某类延迟的分布
  • 某类实例的资源状态

它不适合描述:

  • 某一个请求
  • 某一个用户
  • 某一个 session
  • 某一个 trace

如果一个字段本质上是"明细主键",它通常就不应该成为 label。


2. 治理前后对比

对比一:原始 URL 改为 route 模板

Before:

text 复制代码
http_request_duration_seconds{
  method="GET",
  path="/api/orders/123456/items/9988"
}

After:

text 复制代码
http_request_duration_seconds_bucket{
  method="GET",
  route="/api/orders/:id/items/:item_id",
  le="0.5"
}

为什么 After 更适合 Prometheus:

  • 原始 URL 往往包含业务主键,基数随数据规模增长
  • route 模板有稳定上界,更适合聚合统计
  • histogram bucket 能表达延迟分布,而不需要保留请求明细

这里的核心不是"少几个 label",而是把指标从明细表达改为聚合表达。

对比二:把 request_id / user_id 从 metrics 中移出

Before:

text 复制代码
api_request_total{
  method="POST",
  status="500",
  request_id="req-9f8a",
  user_id="u-123456"
}

After:

text 复制代码
api_request_total{
  method="POST",
  status="500",
  tenant="enterprise",
  error_class="upstream_timeout"
}

配套做法:

  • request_idtrace_id 放入 tracing 或 structured logging
  • user_id 替换为租户、地域、套餐等可聚合维度

为什么 After 更适合 Prometheus:

  • 指标保留了聚合分析和告警需要的维度
  • 明细主键不再造成无上界 Time Series 膨胀
  • 问题定位可以通过 metrics -> logs / traces 的联动完成

Prometheus 适合聚合统计,不适合明细检索。

这条边界一旦模糊,系统就会很快被高基数击穿。


3. 采集侧治理样例

如果某些组件已经输出了不合理标签,优先考虑在采集侧进行收敛,而不是把坏数据先写入 TSDB。

示例一:直接删除高风险 label

yaml 复制代码
scrape_configs:
  - job_name: app
    static_configs:
      - targets: ["app:9090"]
    metric_relabel_configs:
      - action: labeldrop
        regex: "request_id|trace_id|span_id|session_id|pod_uid|container_id"

适用场景:

  • exporter 或业务组件短期内难以改造
  • 已确认这些标签不参与聚合分析
  • 需要先阻断高基数继续扩散

示例二:保留必要标签,丢弃无界标签

yaml 复制代码
scrape_configs:
  - job_name: gateway
    kubernetes_sd_configs:
      - role: pod
    metric_relabel_configs:
      - source_labels: [__name__]
        regex: "http_request_duration_seconds_bucket|http_requests_total"
        action: keep
      - action: labelkeep
        regex: "__name__|job|instance|namespace|pod|service|method|status|route|le"
      - action: labeldrop
        regex: "request_id|trace_id|user_id|device_id|session_id|pod_uid|container_id"

这个配置的意图是:

  • 只保留核心 HTTP 指标
  • 只保留聚合和定位必须的标签
  • 主动丢弃无界或瞬态维度

示例三:对问题指标直接丢弃

yaml 复制代码
scrape_configs:
  - job_name: legacy-app
    static_configs:
      - targets: ["legacy-app:9100"]
    metric_relabel_configs:
      - source_labels: [__name__]
        regex: ".*_by_user_.*|.*_by_session_.*"
        action: drop

适用场景:

  • 业务组件暴露了明显不适合 Prometheus 的指标
  • 这些指标短期内无法重构
  • 继续保留只会增加系统负担

采集侧治理的原则很简单:
不让无界 label 穿透到 TSDB。


4. 运行侧治理:把容量边界显式化

除了删 label,更关键的是建立容量边界:

  • 单实例允许的 Head Series 范围
  • 可接受的 Series Created Rate
  • RSS / Heap 告警阈值
  • 慢查询告警阈值
  • 新业务接入前的 series 规模评估流程

如果没有这些边界,Prometheus 的容量会在业务增长过程中被隐式消耗,直到某次上线或扩容后突然失控。


5. 架构隔离:让 Prometheus 只承载适合它的数据

对高基数治理更成熟的团队,最终都会走向数据分层。

典型思路如下:

text 复制代码
Agent / Exporter
  -> Gateway / Remote Write
    -> 聚合指标 -> Prometheus / VictoriaMetrics
    -> 明细事件 -> Kafka / OLAP / Logs / Trace Backend

如果只看主监控查询链路,也可以简化为:

text 复制代码
+-----------+    scrape    +------------+   remote_write   +-----------------+    query    +---------+
| Exporter  | -----------> | Prometheus | ---------------> | VictoriaMetrics | ---------> | Grafana |
+-----------+              +------------+                  +-----------------+            +---------+

按组件链路展开,也可以简化理解为:

text 复制代码
Exporter
  -> Prometheus
    -> Remote Write
      -> VictoriaMetrics
        -> Grafana

其核心原则不是"统一进一个系统",而是:

  • 聚合指标走稳定、低延迟、低基数链路
  • 明细事件走允许延迟、允许大规模扩展的分析链路
  • 让主监控系统服务于告警、趋势和容量判断,而不是承接明细检索

如果把治理动作串成一条工程流程,通常会更接近下面这个顺序:

text 复制代码
指标设计
   │
label 上界评估
   │
Prometheus 接入评审
   │
采集侧 labeldrop
   │
cardinality dashboard 监控

容量估算:在接入前先算一遍 Series 规模

高基数问题本质上是规模问题,因此容量估算应当尽量前置。

一个实用的粗估算方法是:

text 复制代码
总 series 规模 ~= 指标数 x 实例数 x 关键 label 组合数

例如某类 agent 场景:

  • 50000 个 agent
  • 每个 agent 暴露 200 个核心指标
  • 每个指标平均形成 5 组主要标签组合

那么粗略规模大致为:

text 复制代码
50000 x 200 x 5 = 50000000 series

这个数字并不要求绝对精确,但它足以帮助回答几个工程问题:

  • 是否需要对 Prometheus 做分片
  • 是否要按环境或业务拆实例
  • 是否需要 remote write 或长期存储后端
  • 哪些维度必须在接入前做收敛

如果一个新业务上线前连数量级都没有估算,Prometheus 的容量就只能依赖线上试错。


Prometheus vs VictoriaMetrics

这个问题更适合从"职责分工"而不是"谁绝对更好"来理解。

Prometheus 的优势通常在于:

  • 生态成熟
  • 拉取模型和规则体系完善
  • 与 Alertmanager、Grafana 及大量 exporter 协作紧密

VictoriaMetrics 在一些场景下通常更适合作为大规模承载层,尤其是在:

  • 大规模写入
  • 存储压缩效率
  • 长期存储成本
  • 水平扩展能力

这些方面,经常会体现出更好的工程适配性。

但这并不意味着换了后端就可以忽略高基数治理。

更准确的表述应是:

  • 更适合大规模承载的存储后端,可以提高系统容忍度
  • 但它不能替代正确的指标设计和 label 边界控制

很多生产环境会采用组合架构:

text 复制代码
Prometheus 负责抓取、规则评估和告警
VictoriaMetrics 负责长期存储或更大规模指标承载

这是一种常见实践,但不是唯一正确答案。

是否采用该组合,取决于团队规模、查询模型、成本目标和运维能力。


总结

高基数问题的工程本质,可以归纳为三句话:

  1. Prometheus 的容量压力主要受 Time Series 数量和变化速率驱动,而不只是 sample 数量。
  2. 高基数不等于一定错误,真正需要优先治理的是无上界、不可聚合、持续产生新值的 label。
  3. 有效治理依赖完整方法链条:设计约束、采集收敛、运行监控、容量评估和架构分层。

如果把请求主键、用户主键、瞬态实例 ID 直接写进 metrics,Prometheus 最终承受的不是"更多监控",而是"不适合它处理的数据模型"。

因此更稳妥的实践不是追求"把所有数据都接进去",而是明确边界:

  • 哪些维度属于聚合统计
  • 哪些维度属于事件明细
  • 哪些数据应进入 Prometheus
  • 哪些数据应进入日志、Tracing 或 OLAP 系统

这类边界一旦明确,Prometheus 的稳定性、容量规划和故障定位效率都会明显改善。


附录:常用 PromQL 与上线检查清单

常用 PromQL

1. 查看 TopN Series 指标

promql 复制代码
topk(20, count by (__name__)({__name__=~".+"}))

用途:

  • 快速定位当前时序规模最大的指标名

1.1 查看 job 维度的 Series 分布

promql 复制代码
topk(20, count by (job)({__name__=~".+"}))

用途:

  • 快速判断哪些 job 正在贡献最多的 Time Series
  • 适合先从抓取源头定位问题范围

2. 查看新 Series 速率

promql 复制代码
rate(prometheus_tsdb_head_series_created_total[5m])

用途:

  • 观察是否正在持续生成新的 Time Series

3. 查看某个维度的 Cardinality

promql 复制代码
count(count by (instance) (up))
promql 复制代码
count(count by (pod) (http_requests_total))
promql 复制代码
count(count by (route) (http_request_duration_seconds_count))
promql 复制代码
count(count by (namespace) (up))

用途:

  • 判断某个 label 的实际取值规模是否符合预期
  • 对指定维度做 cardinality 粗查时,可将 namespace 替换为目标 label

4. 发现 Churn 异常的查询思路

promql 复制代码
rate(prometheus_tsdb_head_series_created_total[5m])
-
rate(prometheus_tsdb_head_series_removed_total[5m])

以及:

promql 复制代码
rate(prometheus_tsdb_head_series_created_total[5m])

配合:

promql 复制代码
prometheus_tsdb_head_series

用途:

  • 判断系统是在单纯扩容,还是在异常创建大量新时序
  • 观察新增与淘汰是否同时偏高,从而识别高 churn

上线检查清单

  • 这个 label 是否有天然上界,且上界是否可以估算?
  • 它是否可能按请求、按用户、按 session 或按 trace 持续生成新值?
  • 它是否能被 routebucketstatustenantregion 等聚合维度替代?
  • 新业务接入前,是否做过 series 规模估算?
  • 是否已经建设 Head SeriesSeries Created Rate 的监控和告警?
  • 是否有专门的 cardinality dashboard 用于日常巡检?
  • 是否评估过该指标更适合进入 metrics、logs、tracing 还是 OLAP?
  • 是否在采集侧配置了必要的 metric_relabel_configslabeldropdrop 规则?
  • 如果该指标来源于 Kubernetes 或 Agent,是否确认它属于"有上界的高基"而不是"无上界的高基"?
  • 如果未来规模扩大 2 到 5 倍,这组指标是否仍在当前 Prometheus 实例的容量边界内?

这份清单的目标不是让指标体系变得保守,而是让每一个新增维度都经过基本的工程判断。

相关推荐
IT_陈寒2 小时前
Vite凭什么比Webpack快10倍?5个核心优化原理大揭秘
前端·人工智能·后端
怕浪猫2 小时前
第22章:项目实战与进阶优化——从开发到部署的完整旅程
后端·go·编程语言
摸鱼的春哥2 小时前
你适合养龙虾🦞吗?4类人不适合2类适合
前端·javascript·后端
Moment2 小时前
Agent 开发本质上就是高级点的 CRUD
前端·后端·面试
stark张宇3 小时前
避坑指南:Windows 用户安装 OpenClaw 的正确姿势,拒绝失败率 100%
人工智能·后端·llm
程序员爱钓鱼4 小时前
Go错误处理全解析:errors包实战与最佳实践
前端·后端·go
巫山老妖12 小时前
从零开发一个掘金自动发布 Skill,并上架 Clawhub
后端
颜酱12 小时前
图的数据结构:从「多叉树」到存储与遍历
javascript·后端·算法
雨中飘荡的记忆13 小时前
零拷贝技术深度解析
后端