MONITOR 能看到同一秒内数十至上百条针对同一 key 的高频 GET 请求,随后紧接 SET 回写,且无 EXISTS 等原子判断命令。

缓存击穿发生时,MONITOR 能看到什么异常模式
缓存击穿本质是大量并发请求同时发现某个 key 不存在(或已过期),于是穿透到后端服务。此时 MONITOR 输出里最典型的信号不是错误,而是高频、重复、几乎时间戳对齐的 GET 请求——尤其针对同一个 key。
注意:MONITOR 不会显示“缓存没命中”,它只忠实地打印每条到达 Redis 的命令。所以你要找的是:
- 同一秒内出现数十甚至上百条形如
GET user:10086的日志行 - 这些
GET后紧跟着SET user:10086 ... EX ...(说明应用层在回写) - 中间没有
EXISTS或GETEX等带原子性判断的命令,全是裸GET
用 MONITOR 抓包前必须关掉的干扰项
MONITOR 是全量命令监听,开一次就吃掉可观 CPU 和网络带宽,线上慎用。它本身不区分客户端,所有连接的命令都会混在一起输出,容易淹没关键信号。
实操建议:
- 先用
CLIENT LIST定位疑似高并发的客户端 IP 和id,再用CLIENT SETNAME给它们打标,后续配合redis-cli --monitor --filter(Redis 7.0+)过滤 - 避免在
MONITOR运行期间执行运维命令(如CONFIG REWRITE、BGSAVE),否则日志会被污染 - 不要在主从架构的从节点上运行
MONITOR,它只记录本节点收到的命令,从节点不处理写请求,看不到上游的SET
GET 高频但无 SET 回写?可能是客户端缓存或本地缓存绕过了 Redis
如果 MONITOR 显示某 key 被疯狂 GET,但始终没看到对应 SET,别急着断定是 Redis 层问题。常见真实原因:
- 应用用了两级缓存(如 Caffeine + Redis),
GET失败后直接查 DB 并写入本地缓存,跳过了 Redis 的SET - 前端或网关做了 HTTP 缓存,实际请求根本没发到 Redis 客户端
- 代码里写了
if (redis.get(k) == null) { db.query(); redis.set(k, v); },但redis.set()被异常吞掉或异步丢弃了
这时候 MONITOR 只是“证据链”的一环,必须和应用日志、DB 慢查询、客户端 SDK 的 trace 日志交叉比对。
比 MONITOR 更轻量、更可持续的替代方案
MONITOR 是临时急救工具,不适合长期开启。真正要定位缓存击穿,优先考虑:
- 开启 Redis 的慢日志(
slowlog-log-slower-than 10000),看是否有大量GET命中耗时突增(说明底层在竞争锁或序列化开销大) - 用
INFO commandstats查cmdstat_get:calls=和cmdstat_set:calls=的比例,若 GET 是 SET 的 10 倍以上,且集中在某类 key 前缀,就是强信号 - 在客户端 SDK 层埋点:统计每次
get(key)返回null后是否触发了set(key, ...),这个数据比 Redis 层日志更准
真正难的不是发现击穿,而是确认那个“空窗期”里到底有多少请求漏掉了互斥写入逻辑——这得靠应用层的原子性保障,不是 MONITOR 能覆盖的。


















