面试知识库
高 进阶

热Key问题与解决#

一句话答案#

热 Key 导致单节点瓶颈,解决:本地缓存(Caffeine)+ 读副本分担 + Key 打散到多节点。

核心要点

发现: 监控 QPS 异常 / redis-cli —hotkeys(需 LFU 淘汰策略)/ Redis 8.6+ 的 HOTKEYS 命令

解决:

  1. 本地缓存:JVM 内 Caffeine/Guava Cache
  2. 读副本:从节点分担读请求
  3. Key 打散:key_{random} 分散到多个节点,读取时随机选一个

面试回答(2分钟版)

热 Key 指某个 Key 被高频访问导致该 Key 所在的 Redis 节点成为性能瓶颈,在 Cluster 架构下尤其明显,因为一个 Key 固定在一个 slot 上,只能落在一个分片,加再多分片也分担不了;从库默认不接读请求,要客户端发 READONLY 开启从库读,而且也只能分摊到这个分片自己的几个从库。发现热 Key 主要通过监控 QPS 异常或者用 redis-cli —hotkeys 命令扫描(Redis 8.6 起还有服务端 HOTKEYS 命令,按 CPU 时间和网络字节统计热 Key)。解决方案有三种:第一是 JVM 本地缓存,用 Caffeine 或 Guava Cache 在应用层缓存热数据,请求不到 Redis 直接本地命中,这是最有效的手段;第二是读副本分担,配合客户端读写分离(Cluster 下从节点需 READONLY)把读请求分散到该分片的从节点,但扩展上限就是从库数量,且有复制延迟;第三是 Key 打散,把热 Key 加上随机后缀分散到多个节点,读取时随机选一个副本。实际项目中我倾向于本地缓存优先,因为它直接减少了网络请求,但要注意设置合理的 TTL 和容量上限,并且和 Redis 之间要处理好一致性,通常通过短 TTL、发布订阅通知失效,或 Redis 6.0+ 的服务端辅助客户端缓存(CLIENT TRACKING)来解决。

追问与易错

追问方向:

  • “怎么发现热 Key?”→ redis-cli —hotkeys 命令扫描(需开启 LFU 策略)、Redis 8.6+ 的 HOTKEYS 命令(按 CPU 时间/网络字节采样统计,不依赖 LFU)、监控单节点 QPS 异常飙升、客户端 SDK 统计 key 访问频率、proxy 层(如 Twemproxy)统计热点
  • “本地缓存和 Redis 怎么保持一致?”→ 设置较短的本地缓存 TTL(如几秒到几十秒)容忍短暂不一致;或通过 Redis Pub/Sub 广播失效通知,各节点收到通知后清除本地缓存;Redis 6.0+ 自带服务端辅助的客户端缓存(CLIENT TRACKING,默认模式按 key 追踪、BCAST 模式按前缀广播,key 被修改时服务端推送失效消息);也可结合版本号做校验
  • “多级缓存更新顺序?”→ 写入时先更新数据库、再删除 Redis 缓存、本地缓存通过短 TTL 自动失效或接收通知失效;读取时先查本地缓存、再查 Redis、最后查数据库并逐级回填

易错点:

  • ❌ 加从库/加分片就能解决热 Key——热 Key 只在一个 slot、一个分片;从库默认不接读(需 READONLY),且只能分摊到该分片的几个从库
  • ❌ 本地缓存不会过期——必须设 TTL