最新下载
热门教程
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
Prometheus 如何处理高基数带来的性能下降
时间:2026-08-24 19:53:49 编辑:袖梨 来源:一聚教程网
核心是阻止高基数数据进入内存,通过采集、写入、查询三环节拦截:先定位爆炸源头(查序列数、指标分布、危险标签),再源头裁剪(labeldrop、路径归一化、禁用元标签),接着预聚合(recording rules),最后加限制兜底(max-series、admin API、exporter改造)。
核心是不让高基数数据进内存——在采集、写入、查询三个环节层层拦截,而不是等它进来再“救火”。
先定位爆炸源头
别猜,直接查指标和标签的实际分布:
- 看总序列数是否持续上涨:查 prometheus_tsdb_head_series,确认 Head Block 是否在“膨胀”
- 统计各指标的序列数量:用 count by (__name__) ({__name__=~".+"}) 找出前几名“大户”
- 盯住危险标签值:比如 label_values(http_request_duration_seconds_bucket, url),如果返回几千个 URL,基本就是问题所在
- 特别留意 user_id、request_id、trace_id、动态 path(如 /api/users/12345) 这类无界标签
从源头裁剪标签
让高基数标签根本不出现在时间序列里:
- 用 labeldrop 直接丢弃:在 scrape_configs 的 relabel_configs 中写
- action: labeldrop; source_labels: [url]或[user_id] - 对必须保留的路径做归一化:用正则把
/api/v1/orders/789→/api/v1/orders/:id,再用labelmap或replacement覆盖原标签 - 禁用默认元数据标签:如 __meta_kubernetes_pod_uid、__meta_kubernetes_pod_ip,除非业务明确依赖
用 recording rules 预聚合替代原始查询
不查爆炸性原始指标,只查聚合后结果:
- 把
http_requests_total{method, status, url}拆成两层:一层按job, method, status聚合(低基数),另一层只保留关键白名单 URL(如/health、/login) - 定义 recording rule:
job:http_requests_total:rate5m = sum by (job, method, status) (rate(http_requests_total[5m])) - 所有告警、看板、下游系统都基于这类聚合指标,原始高基数指标可设为
drop或仅短期保留用于调试
加限制和兜底机制
防漏网之鱼引发雪崩:
- 启动时加参数:--storage.tsdb.max-series-per-metric=50000,超限自动拒绝写入
- 启用 admin API(
--web.enable-admin-api),配合脚本定期调用/api/v1/admin/tsdb/delete_series清理已确认废弃的系列(注意指定时间范围,慎用) - 对 exporter 做改造:比如 Kafka exporter 等,从源头控制暴露的标签维度和取值范围