一聚教程网:一个值得你收藏的教程网站

热门教程

Prometheus 如何处理高基数带来的性能下降

时间:2026-08-24 19:53:49 编辑:袖梨 来源:一聚教程网

核心是阻止高基数数据进入内存,通过采集、写入、查询三环节拦截:先定位爆炸源头(查序列数、指标分布、危险标签),再源头裁剪(labeldrop、路径归一化、禁用元标签),接着预聚合(recording rules),最后加限制兜底(max-series、admin API、exporter改造)。

核心是不让高基数数据进内存——在采集、写入、查询三个环节层层拦截,而不是等它进来再“救火”。

先定位爆炸源头

别猜,直接查指标和标签的实际分布:

  1. 看总序列数是否持续上涨:查 prometheus_tsdb_head_series,确认 Head Block 是否在“膨胀”
  2. 统计各指标的序列数量:用 count by (__name__) ({__name__=~".+"}) 找出前几名“大户”
  3. 盯住危险标签值:比如 label_values(http_request_duration_seconds_bucket, url),如果返回几千个 URL,基本就是问题所在
  4. 特别留意 user_id、request_id、trace_id、动态 path(如 /api/users/12345) 这类无界标签

从源头裁剪标签

让高基数标签根本不出现在时间序列里:

  1. labeldrop 直接丢弃:在 scrape_configs 的 relabel_configs 中写 - action: labeldrop; source_labels: [url][user_id]
  2. 对必须保留的路径做归一化:用正则把 /api/v1/orders/789/api/v1/orders/:id,再用 labelmapreplacement 覆盖原标签
  3. 禁用默认元数据标签:如 __meta_kubernetes_pod_uid__meta_kubernetes_pod_ip,除非业务明确依赖

用 recording rules 预聚合替代原始查询

不查爆炸性原始指标,只查聚合后结果:

  1. http_requests_total{method, status, url} 拆成两层:一层按 job, method, status 聚合(低基数),另一层只保留关键白名单 URL(如 /health/login
  2. 定义 recording rule:job:http_requests_total:rate5m = sum by (job, method, status) (rate(http_requests_total[5m]))
  3. 所有告警、看板、下游系统都基于这类聚合指标,原始高基数指标可设为 drop 或仅短期保留用于调试

加限制和兜底机制

防漏网之鱼引发雪崩:

  1. 启动时加参数:--storage.tsdb.max-series-per-metric=50000,超限自动拒绝写入
  2. 启用 admin API(--web.enable-admin-api),配合脚本定期调用 /api/v1/admin/tsdb/delete_series 清理已确认废弃的系列(注意指定时间范围,慎用)
  3. 对 exporter 做改造:比如 Kafka exporter 等,从源头控制暴露的标签维度和取值范围

热门栏目