client tracking 不能防缓存击穿,因其仅在 key 变更时通知客户端缓存失效,不拦截请求、不控制并发、不干预缓存未命中时的重建逻辑,对过期驱逐无通知,也不处理空值缓存。

Redis 6 的 CLIENT TRACKING 功能不能防击穿。 它不拦截请求、不控制并发、不干预缓存未命中时的业务逻辑,只负责在 key 变更时通知客户端“你本地存的那个值可能过期了”。击穿发生在缓存失效瞬间的并发重建阶段,而 tracking 根本不参与这个过程。
为什么 CLIENT TRACKING 对缓存击穿无效
缓存击穿的核心问题是:一个热点 key 刚过期,多个请求同时发现缓存 miss,全部涌向数据库。解决它需要的是「串行化重建」或「延迟暴露失效」,而 CLIENT TRACKING 做的是另一件事:
- 它只在服务端记录「哪些客户端读过哪些 key」,然后在
SET/DEL/INCR等写操作发生时推送 invalidation message - 它不阻止任何请求访问 Redis,也不影响
GET返回 nil 的行为 - 它不感知 key 是否设置了过期时间,更不干预「过期后第一个请求要不要重建」
- 即使你开了
CLIENT TRACKING ON,当 key 过期被驱逐后,GET依然返回 nil,tracking 不会发通知(因为 key 已不存在,服务端无从追踪)
真正能防击穿的 Redis 原生方案只有这几种
别把 tracking 当成银弹。生产中防击穿,得靠下面这些明确作用于「重建阶段」的机制:
Redis 缓存和数据结构管理技能。通过自然语言操作 Redis,支持 String、Hash、List、Set、ZSet、Stream 等数据结构操作。当用户提到 Redis、缓存、消息队列、会话存储时使用此技能。
-
SETNX+EXPIRE组合实现互斥锁:第一个请求用SETNX key-lock 1 EX 30抢锁,成功则查库重建;其他请求轮询等待或直接返回旧值 - 逻辑过期:写入缓存时 value 封装为
{"data": "...", "expireAt": 1725545940},读取时先判断expireAt是否过期,过期再异步重建,期间仍返回旧数据 - 提前预热 + 随机过期时间:对已知热点 key,在部署或定时任务中主动
SET并设置带随机偏移的EX(如EX 3600 + rand(300)),避免集中失效 - 永不过期 + 后台刷新:key 不设 TTL,由独立线程定期
GET检查逻辑过期并触发更新,完全规避失效窗口
CLIENT TRACKING 的真实适用场景和风险点
它适合解决「读多写少、变更可控、客户端可信」的本地缓存一致性问题,比如内部配置项、省份字典、菜单结构。但用错地方反而放大风险:
- 如果开启
CLIENT TRACKING ON却没配REDIRECT或使用 RESP3,客户端收不到任何失效通知,本地缓存永远不更新 - 如果误将高频变更的 key(如实时计数器、用户 session)加入 tracking,服务端内存暴涨,且频繁推送导致网络开销激增
- 如果客户端不做
NOLOOP,自己改完 key 又收到自己的 invalidation,可能触发重复处理或死循环 - 它完全不管空值缓存——而击穿常伴随大量空查询,tracking 对此毫无约束力
真正要防击穿,得盯紧「重建那一刻」发生了什么。tracking 是个事后通知机制,不是事前拦截器。别让它出现在你的击穿防护链路上,否则上线后压测一跑,数据库照样被打穿。










