多维度优化降低Prometheus资源消耗的实践

最近在玩 Prometheus ,我在grafana上使用了以下PromQL查询:

sum by (user) (
  rate(iftop_traffic_bytes_total{direction="send",user!=""}[1m])
) > 1000

这个查询导致 Prometheus 主机系统负载高的问题。通过count by (__name__)({__name__=~".+"})分析发现,iftop_traffic_bytes_total指标存在约5万个时间序列,其中user标签的基数占比超过75%。

一、分阶段优化过程

阶段一:查询层优化

1. 过滤无效标签

user!~"(?:^$|default|system)"

该操作减少约8%的时间序列数量,但查询延迟仅从3.2s降至3.0s,效果有限。

2. 调整时间窗口

将计算窗口从[1m]缩短至[30s]

原始执行时间:3.2s → 2.7s

但观察到流量曲线有些波动,pass。

阶段二:数据源治理

3. 指标生成层过滤

通过改造指标生成脚本,在数据源头排除无效数据:

# 原始数据采集脚本片段
awk '/iftop_traffic_bytes_total/ && $6 != "" {print $0}' raw_metrics.log > metrics.prom

优化效果:

  • 指标生成量减少12%
  • user标签基数从5200下降至4600
  • Prometheus TSDB写入速率降低15%

4. 采集配置增强

prometheus.yml中补充过滤规则:

metric_relabel_configs:
- source_labels: [user]
  regex: '^(?:|default|system)$'
  action: drop

双重保障确保无效数据不会进入存储环节。

阶段三:计算层优化

5. 预计算规则

配置Recording Rules实现查询逻辑固化:

- record: job:iftop_traffic_bytes:rate1m
  expr: |
    rate(iftop_traffic_bytes_total{
      direction="send"
    }[1m])

优化后的查询语句简化为:

sum by (user) (job:iftop_traffic_bytes:rate1m) > 1000

二、效果验证

通过多维度优化措施组合实施,系统指标变化如下:

优化阶段 时间序列数量 查询延迟 内存消耗
原始状态 52,000 3200ms 1.2GB
查询层优化后 47,800 2700ms 900MB
数据源治理后 42,000 2200ms 750MB
预计算规则启用后 820 420ms 150MB

通过rate(prometheus_engine_query_duration_seconds_sum[1h])指标观测,查询延迟P99值下降89%。

三、衍生效益

基于优化后的数据模型,我扩展实现了以下监控指标:

# 实时在线用户数
count(sum by (user)(job:iftop_traffic_bytes:rate1m) > bool 1)

四、经验总结

  1. 源头治理优先:在指标生成环节过滤无效数据,比后期处理更高效
  2. 分层防御体系:结合脚本过滤+metric_relabel_configs构建双重保障
  3. 预计算价值:Recording Rules将复杂查询转换为简单检索,效果显著
  4. 基数监控:建立count(count by (user)({__name__=~".+"}))例行检查机制

Shell 脚本 while 循环只执行一次的问题 Prometheus调优:干掉高基数和慢查询