redis 6.2 的 client tracking 是唯一服务端主动通知缓存失效的机制,需配合 resp3(hello 3)、合理 tracking 模式(推荐 optout)及客户端幂等清理、output buffer 调优与循环消费,否则易丢消息或内存暴涨。

Redis 6.2 中 CLIENT TRACKING 是唯一能实现服务端主动通知客户端缓存失效的机制,但必须配合 RESP3 协议、合理的 tracking 模式和客户端侧状态管理,否则会丢消息或内存暴涨。
CLIENT TRACKING on 必须搭配 HELLO 3 才生效
Redis 6.0 引入了 CLIENT TRACKING,但 redis-cli 直到 6.2 才支持 RESP3。如果你用 6.2 的服务器却连着 6.0 的 redis-cli,执行 CLIENT TRACKING on 看似成功,实际不会注册 tracking 状态,后续键变更也不会收到失效推送。
- 必须先发
HELLO 3切换协议,再执行CLIENT TRACKING on - 用
CLIENT LIST查看连接时,flags字段应含T(表示 tracking enabled),否则说明没真正开启 - Java 客户端如 Lettuce 需显式启用 RESP3:构造
RedisClient时传入ClientResources.builder().ioThreadPoolSize(...).build()并确认日志有Using protocol version: 3
三种 tracking 模式选错会导致连接数爆炸或漏通知
CLIENT TRACKING 支持 normal、optin、optout 三种模式,不是“越自动越好”:
-
normal:默认模式,所有GET、HGET等读命令涉及的 key 都被自动 tracking —— 但每个连接会维护一张 key 映射表,高并发下这张表本身吃内存,且 key 变更时广播开销大 -
optin:只对显式加REDIRECT或BROADCAST参数的请求才 tracking,适合只对少数热点 key 做本地缓存的场景 -
optout:默认不 tracking,对个别不想被跟踪的 key 加NOLOOP标记 —— 这是多数业务最实用的选择,比如用户资料 key 全部 tracking,但临时 token key 显式排除
误用 normal 模式 + 大量短连接,可能让 Redis 内存中堆积数万条无效 tracking 记录,触发 client-output-buffer-limit 溢出断连。
Redis 缓存和数据结构管理技能。通过自然语言操作 Redis,支持 String、Hash、List、Set、ZSet、Stream 等数据结构操作。当用户提到 Redis、缓存、消息队列、会话存储时使用此技能。
服务端需配置 client-output-buffer-limit pubsub 防止推送积压
tracking 失效消息走的是 Pub/Sub 通道,但不是独立连接,而是复用当前 client 连接的输出缓冲区。一旦客户端处理慢或网络卡顿,失效消息就会在 output buffer 里堆积:
- 默认
client-output-buffer-limit pubsub是32mb 8mb 60(硬限 32MB,软限 8MB 持续 60 秒就断连) - 高峰期单次推送可能触发上百个 key 失效,若客户端未及时 read,buffer 很快打满
- 必须调大该限制,例如设为
client-output-buffer-limit pubsub 256mb 64mb 300,并监控CLIENT LIST中的omem字段(当前 output buffer 占用) - 客户端代码里不能只做一次
read()就停,要循环消费直到 buffer 空,否则下次推送直接覆盖旧消息
本地缓存清理逻辑必须幂等且带防重
Redis 推送的失效消息只是“key 可能变了”,不是“key 一定被改了”。网络重传、客户端重复消费、服务重启后重连都会导致同一条失效消息来多次:
- 不要直接删本地缓存,而是加一层
invalidate(key, version),用 Redis 的INCR或时间戳生成单调递增版本号 - 本地缓存命中时,校验存储的版本是否低于当前版本,低则穿透加载并更新本地版本
- 避免用
DEL命令清空整个本地 cache map,这会造成雪崩;应精确到 key 粒度
最关键的细节:tracking 不保证消息 100% 到达,也不保证顺序。它本质是尽力而为的提示机制,最终一致性靠客户端自己兜底 —— 这点常被文档忽略,但线上故障多源于此。










