CLIENT TRACKING 不能防止缓存击穿,它仅在 key 被写操作修改时异步通知客户端失效本地缓存,不感知过期、不干预并发回源、不参与缓存重建,对击穿场景完全无效;防击穿必须用服务端互斥锁或逻辑过期方案。

CLIENT TRACKING 不能防止缓存击穿,强行用它挡击穿反而会让问题更隐蔽、更难排查。
Redis 6.0 的客户端缓存(CLIENT TRACKING)是为「读多写少 + 客户端本地有足够内存」的场景设计的,它的作用是让 Redis 主动通知客户端“你缓存的某个 key 被改了”,从而让客户端主动失效本地副本。它**不参与缓存重建流程**,也不控制并发访问,更不会阻塞或协调多个请求对同一个失效 key 的回源行为。
为什么 CLIENT TRACKING 对击穿完全无效
缓存击穿的本质是:一个热点 key 过期后,多个并发请求同时发现缓存 miss,全部涌向数据库。而 CLIENT TRACKING 在这个过程中:
- 不感知 key 是否过期 —— 它只在 key 被
SET、DEL、INCR等写操作修改时触发 invalidation - 不干预服务端逻辑 —— 它不帮你加锁、不延缓请求、不合并查询、不延迟响应
- 不解决“谁来重建缓存” —— 它甚至不知道当前有没有缓存,更不管重建该由谁做、做几次
- 在击穿发生时,客户端根本没缓存(因为 key 已过期),所以 tracking 机制压根没被激活
误用 CLIENT TRACKING 反而放大风险
有人尝试开启 tracking 后,在应用层再加一层本地 Map 缓存,以为能“分担压力”。但实际会遇到这些坑:
- 本地缓存未命中时,仍会并发打 DB —— tracking 不提供任何同步保护
- Redis 通知客户端失效是异步、不可靠的(可能丢包、延迟高),导致本地缓存长期脏读
- 客户端连接数暴涨时,Redis 的 tracking table 内存占用线性增长,可能触发 OOM 或连接拒绝
- 无法与 Spring Cache、Caffeine 等已有缓存抽象集成,必须手写全套生命周期管理
真正防击穿该用什么
击穿是服务端缓存层的问题,必须在服务端拦截和协调。可靠方案只有两类:
Redis 缓存和数据结构管理技能。通过自然语言操作 Redis,支持 String、Hash、List、Set、ZSet、Stream 等数据结构操作。当用户提到 Redis、缓存、消息队列、会话存储时使用此技能。
-
互斥锁(Mutex Lock):用
SET key value NX EX 30争锁,成功者查 DB 并写缓存,失败者等待重试或短暂休眠后重读。适合一致性要求高、重建耗时不长的场景 -
逻辑过期(Logical Expiration):缓存 value 中嵌入一个
expireTime字段,key 本身永不过期;读取时先判断逻辑时间是否过期,过期则异步刷新,当前请求仍返回旧值。适合容忍短时脏数据的热点数据
两者都必须在业务代码中显式实现,且需配合合理的超时、重试、降级策略。别指望靠客户端侧的机制绕过服务端协调。
CLIENT TRACKING 唯一适用的场景
它只适合一种情况:你已有一套稳定的服务端缓存(比如用互斥锁防住了击穿),且客户端是 Web 浏览器、移动端 App 或边缘节点,需要在本地缓存高频读、低频更新的数据(如用户配置、菜单结构),同时能接受最终一致性。此时开启 CLIENT TRACKING ON REDIRECT 配合 RESP3 协议,才有点价值。
把 CLIENT TRACKING 当成防击穿手段,就像用雨伞挡海啸——方向错了,力气白费。

















