缓存击穿不能仅凭slowlog-duration判断,因其本质是高频并发请求在key过期后集中打到DB并争抢重建,Redis命令本身执行快(如GET通常200–800μs),易被高阈值漏判;真正标志是同一key的GET/SET/DEL在毫秒级窗口内密集交替出现。

慢查询日志本身不直接标记“击穿”,但能暴露击穿发生时的典型行为模式——关键不在单条命令多慢,而在同一 key 的 GET、SET、DEL 在毫秒级窗口内密集交替出现。
为什么不能只看 slowlog-duration 判断击穿
缓存击穿的本质是大量并发请求在 key 过期后同时打到 DB,再由业务线程争抢重建缓存。Redis 层面的命令执行本身很快(GET 通常 duration 字段往往不高(比如 200–800μs),容易被误判为“不慢”。真正异常的是频率和组合模式。
- 单条
GET user:12345耗时 400μs —— 正常 - 同一秒内出现 17 条
GET user:12345+ 5 条SET user:12345+ 2 条DEL user:12345—— 高度可疑 - 这些记录在
SLOWLOG GET 100结果里连续排列,且time时间戳差值
如何从 SLOWLOG GET 输出识别击穿链路
运行 redis-cli SLOWLOG GET 100 后,重点扫视 command 字段中是否出现“三连模式”:
- 先有一批
GET <key>(缓存未命中) - 紧跟着若干
SET <key>或SETEX <key>(缓存重建) - 中间或前后夹杂
DEL <key>(可能是预热清理或双删逻辑) - 所有命令的
<key>具有相同业务前缀(如item:、order:),且不是随机生成的 UUID 类 key
示例片段(简化显示):
Redis 缓存和数据结构管理技能。通过自然语言操作 Redis,支持 String、Hash、List、Set、ZSet、Stream 等数据结构操作。当用户提到 Redis、缓存、消息队列、会话存储时使用此技能。
3) 1) (integer) 98765
2) (integer) 1725572040
3) (integer) 320
4) 1) "GET"
2) "item:889911"
4) 1) (integer) 98764
2) (integer) 1725572040
3) (integer) 410
4) 1) "GET"
2) "item:889911"
5) 1) (integer) 98763
2) (integer) 1725572040
3) (integer) 680
4) 1) "SET"
2) "item:889911"
3) "xxx"
注意:时间戳 1725572040 对应秒级时间,三条记录落在同一秒内,就是典型线索。
配合 INFO stats 和 client list 验证击穿三要素
仅靠 SLOWLOG 不足以确认击穿,必须交叉验证“key 曾存在、已过期、DB 有数据”这三要素:
- 查
INFO stats中的keyspace_misses:若该 key 所在时间段内突增(比如从 50/s 跳到 3200/s),支持“未命中集中爆发” - 用
redis-cli --scan --pattern "item:889911"确认 key 当前不存在;再用TTL item:889911返回-2(不存在)或-1(永不过期,排除) - 查
CLIENT LIST中对应客户端 IP 的连接数和 idle 时间:若大量客户端在 key 失效前后建立新连接、且idle极短( - 比对应用日志:该 key 的 DB 查询耗时是否同步飙升?如果有,就闭环了
容易忽略的关键点:SCAN/KEYS 不是击穿,但会掩盖它
SCAN 或 KEYS * 这类全量扫描命令一旦出现在 slowlog 里,会制造高频访问假象,干扰判断。它们的特点是:command 字段含 SCAN 或 KEYS,且 duration 往往 > 5ms(因遍历键空间)。这类操作属于运维误触或低效代码,不是业务热点,更不是击穿。
真正危险的是:你把 SCAN 当成击穿去优化,却放过了那个每秒被 5000 次 GET 冲击的 item:889911 —— 它没进 slowlog 是因为太“快”,而你的阈值设成了 10000μs。

















