2、缓存命中率监控体系:监控指标设计、Prometheus+Grafana搭建、关键指标采集、告警阈值设置

大家好,我是你们的老朋友。今天我们来聊聊缓存命中率的监控体系。说实话,我见过太多团队,缓存用得很嗨,但一问命中率多少,全都傻眼。没有监控,你根本不知道缓存到底在帮你还是坑你。

我个人习惯,做任何系统优化之前,先把监控搭好。为什么?因为你得知道现状,才能谈优化。缓存命中率监控,说白了就是给缓存系统装个仪表盘,让你随时知道它跑得怎么样。

2.1 监控指标设计:到底该看什么?

很多同学一上来就问:「命中率怎么看?」其实命中率只是冰山一角。我建议你至少关注以下四个维度的指标:

指标类别 具体指标 说明
命中率 缓存命中率、未命中率 核心指标,反映缓存有效性
吞吐量 QPS、请求总数、命中次数、未命中次数 了解系统负载情况
延迟 平均延迟、P99延迟 缓存响应速度,影响用户体验
容量 已用内存、键数量、过期键数量 防止内存溢出或数据淘汰

嗯,这里要注意:命中率不能只看平均值。我在项目中遇到过,整体命中率95%,但某个热点key的命中率只有30%。所以,我建议你按业务维度拆分,比如按接口、按用户群体、按时间段。

核心原则:监控指标要能回答三个问题——缓存有没有用?缓存够不够用?缓存快不快?

2.2 Prometheus+Grafana搭建:从零开始

讲真,Prometheus+Grafana这套组合,已经是业界标配了。我几乎每个项目都会用。搭建过程其实不复杂,但有几个坑我得提前告诉你。

先看架构图,我画了一张帮你理解整体流程:

应用服务 Redis/Memcached Exporter Prometheus Grafana AlertManager 采集指标 存储/查询 可视化 告警通知

这张图展示了数据流向:应用和缓存通过Exporter暴露指标,Prometheus定期拉取,Grafana负责展示,AlertManager处理告警。说白了,就是一条流水线。

2.3 关键指标采集:代码怎么写?

我直接给你看一个实际可用的例子。假设你用Redis,配合redis_exporter,配置Prometheus采集:

# prometheus.yml 配置片段
scrape_configs:
  - job_name: 'redis'
    static_configs:
      - targets: ['localhost:9121']  # redis_exporter端口
    metrics_path: '/metrics'
    scrape_interval: 10s  # 我习惯10秒采集一次,太频繁没必要

如果你用Java应用,想采集业务层面的命中率,可以这样暴露自定义指标:

// 使用Micrometer + Prometheus注册表
MeterRegistry registry = new PrometheusMeterRegistry(PrometheusConfig.DEFAULT);

// 定义计数器
Counter cacheHitCounter = Counter.builder("cache.hits")
    .tag("cache_name", "user_cache")
    .register(registry);

Counter cacheMissCounter = Counter.builder("cache.misses")
    .tag("cache_name", "user_cache")
    .register(registry);

// 查询缓存时
Object value = cache.get(key);
if (value != null) {
    cacheHitCounter.increment();
} else {
    cacheMissCounter.increment();
}

嗯,这里有个小技巧:别忘了加标签。我建议你至少加上cache_name、business_type、method_name这几个标签,方便后续按维度分析。

避坑指南:我曾经犯过一个错误——把所有缓存的命中率混在一起统计。结果某个接口的命中率掉到20%都没发现。后来按接口拆分,问题一目了然。所以,标签粒度要细。

2.4 告警阈值设置:多少算低?

这是大家最关心的问题。说实话,没有标准答案。不同业务、不同场景,阈值天差地别。但我可以给你一些参考值:

缓存类型 正常范围 警告阈值 严重阈值
本地缓存(Caffeine/Guava) 90%-99% < 85% < 70%
分布式缓存(Redis) 85%-95% < 80% < 60%
CDN缓存 90%-98% < 85% < 75%
数据库查询缓存 70%-90% < 60% < 40%

你想想看,为什么本地缓存阈值要设得高?因为本地缓存容量小、成本低,命中率低了直接拖垮数据库。而Redis容量大,命中率低一点还能接受。

我个人的告警规则是这样写的:

# Prometheus告警规则
groups:
  - name: cache_alerts
    rules:
      - alert: CacheHitRateLow
        expr: |
          (rate(cache_hits_total[5m]) 
           / (rate(cache_hits_total[5m]) + rate(cache_misses_total[5m]))) 
          * 100 < 80
        for: 5m
        labels:
          severity: warning
        annotations:
          summary: "缓存命中率低于80%"
          description: "缓存 {{ $labels.cache_name }} 命中率仅 {{ $value | humanize }}%"

注意:告警阈值不是一成不变的。我建议你上线后先观察一周,根据实际数据调整。比如,某个业务高峰期命中率会自然下降,这时候阈值就得放宽。

2.5 Grafana仪表盘:可视化展示

指标有了,告警有了,接下来就是展示。我习惯在Grafana上建一个「缓存总览」仪表盘,包含以下面板:

  • 命中率趋势图:按时间序列展示,一眼看出波动
  • QPS与命中率对比:看流量变化对命中率的影响
  • Top 10 低命中率Key:快速定位问题
  • 内存使用率:防止缓存撑爆
  • 延迟热力图:发现响应慢的时段

举个例子,命中率趋势图的PromQL查询:

# 命中率(5分钟滑动窗口)
100 * (
  sum(rate(cache_hits_total[5m]))
  /
  (sum(rate(cache_hits_total[5m])) + sum(rate(cache_misses_total[5m])))
)

说实话,这个查询很基础,但够用。如果你需要按标签分组,可以加上 by (cache_name)。

我的经验:仪表盘不要放太多面板,7-9个最合适。太多反而看不清重点。我一般把最重要的命中率放在左上角,因为人眼习惯从左到右、从上到下看。

好了,关于缓存命中率监控体系,今天就聊到这里。记住:没有监控的缓存,就像闭着眼睛开车。把Prometheus+Grafana搭起来,把指标采起来,把告警设起来,你才能放心地优化缓存。

想要更多资料,联系可可