← 返回题目列表

什么是缓存的热点 Key 和大 Key 问题?如何解决?

高频 中等 第 7 / 25 题 更新于 2026/07/28
缓存热点key大keyRedis优化

简化版

热点 Key(Hot Key):某个 key 被极高频率访问(如爆款商品、大 V),所有请求集中打到存这个 key 的单个 Redis 节点上,导致该节点负载过高、成为瓶颈,甚至被打挂。大 Key(Big Key):某个 key 的value 特别大(如几 MB 的字符串、几百万元素的集合),读写它会阻塞 Redis、占满网络带宽、内存分布不均。热点 key 靠多级缓存、本地缓存、key 打散/复制解决;大 key 靠拆分成多个小 key、用合适的数据结构、异步删除解决。

详细版

热点 Key 的问题与解决:

  • 问题:请求集中在单节点,该节点 CPU/网络打满,其他节点闲着(负载不均),甚至节点被打垮引发缓存击穿。
  • 解决
    • 本地缓存/多级缓存:把热点 key 也缓存到应用本地,挡掉大部分对 Redis 的请求。
    • 热点 key 复制打散:把一个热点 key 复制成多个副本(key#1key#2…)分散到不同节点,请求随机读一个副本,分摊压力。
    • 读写分离 + 从节点扩容:热点读请求分摊到多个从节点。

大 Key 的问题与解决:

  • 问题:单次读写大 value 耗时长,会阻塞 Redis 单线程(其他请求排队);网络传输占带宽;删除大 key 会长时间阻塞;集群下内存倾斜。
  • 解决
    • 拆分:把大 key 拆成多个小 key(如大 Hash 按字段分片成多个小 Hash)。
    • 合适的数据结构:用 Hash/Set 存对象字段,而非把整个大 JSON 塞进一个 String。
    • 异步删除:用 UNLINK(非阻塞删除)代替 DEL,避免删大 key 时阻塞。

完整版教学

一、热点 Key:流量都挤在一个节点上

Redis 集群把数据按 key 分片到不同节点。正常情况下流量均匀分布在各节点。但如果某个 key 是超级热点——比如双十一的爆款商品详情、某明星的微博、秒杀商品的库存——那么对这个 key 的海量请求会全部落到存它的那一个节点上

后果:

  • 单节点被打爆:该节点 CPU、网络带宽被这一个热点 key 占满,QPS 达到上限,响应变慢甚至宕机。
  • 负载严重不均:集群其他节点很闲,但这一个节点忙死——扩容整个集群也没用,因为一个 key 只在一个节点上。
  • 一旦这个热点 key 失效,还会引发缓存击穿,大量请求压向 DB。

二、热点 Key 的解决思路:分摊 + 前置拦截

核心是别让所有请求都挤到一个 Redis 节点

① 多级缓存 / 本地缓存(最有效)。 把热点 key 也缓存到应用的本地内存(Caffeine)。这样大部分请求在应用本地就命中了,根本不用访问 Redis——直接把压力挡在 Redis 之前。这是应对热点 key 最常用、最有效的手段。

② 热点 key 复制打散。 把一个热点 key 复制成 N 个副本,存到不同节点:hotkey#1hotkey#2、…、hotkey#N,内容都一样。读的时候随机选一个副本读,把原本集中在一个节点的请求分摊到 N 个节点。代价是更新时要同时更新 N 个副本。

③ 读写分离、从节点扩容。 热点大多是读请求,可以配置多个从节点,把读请求分摊到多个从节点上。

④ 热点探测。 用工具(如 JD 的 hotkey、字节的探测方案)实时发现哪些 key 变热了,动态把它们提升到本地缓存或做打散处理。

三、大 Key:一个 value 太大惹的祸

大 Key 指某个 key 对应的 value 特别大,常见几种:

  • 大 String:一个 value 几 MB(如把整个大 JSON、大文件塞进一个 key)。
  • 大集合:一个 Hash/List/Set/ZSet 里有几十万、几百万个元素。

大 key 的危害(关键要理解 Redis 是单线程处理命令的):

  • 阻塞 Redis:读写一个大 value 耗时长,而 Redis 单线程一次只能处理一个命令,处理大 key 期间,其他所有请求都被阻塞排队,整个 Redis 卡顿。
  • 网络拥塞:传输几 MB 的 value 占满网络带宽,拖慢其他请求。
  • 删除阻塞DEL 一个有几百万元素的集合,要一次性释放大量内存,会长时间阻塞
  • 内存倾斜:集群下,含大 key 的节点内存暴涨,负载不均。

四、大 Key 的解决思路:拆分 + 合理结构 + 异步删

① 拆分大 key。 把一个大 key 拆成多个小 key。例如一个存了 100 万字段的大 Hash,可以按字段哈希拆成 100 个小 Hash(hash:0 ~ hash:99),每个存 1 万字段。读写时根据字段算出落在哪个小 Hash。这样把压力和内存分散开。

② 选对数据结构。 不要把整个大对象塞进一个 String。如果只需要读对象的某几个字段,用 Hash 存(可以只读需要的字段 HGET,不用把整个对象取出来)。用合适的结构避免「读一点点数据却要传输整个大 value」。

③ 异步删除大 key。 删除大 key 用 UNLINK 而非 DEL——UNLINK 只是把 key 从键空间摘除(O(1)),真正的内存回收放到后台异步线程做,不阻塞主线程。Redis 4.0+ 还可开启 lazyfree 相关配置让过期/淘汰的大 key 也异步释放。

④ 提前发现大 key。redis-cli --bigkeys 扫描、或 MEMORY USAGE 分析,定期排查大 key 并治理。

五、热点 Key vs 大 Key:两个不同的问题

热点 Key大 Key
问题根源访问频率太高value 体积太大
主要危害单节点被打爆、负载不均阻塞 Redis 单线程、占带宽
核心解法多级缓存、复制打散、扩从节点拆分、选对结构、异步删除

别把两者搞混:热点 key 是「一个 key 被访问太多次」,大 key 是「一个 key 存的数据太大」。一个热点 key 不一定大,一个大 key 也不一定热。

六、常见误区与追问

考点正确口径
热点 Key单个 key 访问量极高,压垮缓存节点或网络
大 Key单个 key value 很大,造成阻塞、慢查询、迁移困难
治理拆分、限流、本地缓存、异步处理、数据结构优化
hot key:
product:100 gets 200000 QPS -> one Redis shard overloaded

big key:
hash user_events has 5,000,000 fields
delete or hgetall may block event loop

热点 key 是访问太集中,大 key 是体积太大;一个偏流量,一个偏数据结构。

  • 误区:热点 Key 和大 Key 是同一个问题。 热点关注访问频率,大 Key 关注单个键占用空间或元素数量。
  • 误区:大 Key 只浪费内存。 大 Key 还会导致慢命令、阻塞主线程、迁移困难和网络突增。
  • 误区:热点 Key 只能靠扩容 Redis。 单 key 仍可能落在单分片,要做本地缓存、热点复制、限流或拆 key。
  • 追问:如何发现热点 Key? 可用 Redis hotkeys、代理统计、慢日志、业务埋点和实例流量倾斜监控。
  • 追问:大 Key 如何拆? 按业务维度分片,如按日期、用户段、分页桶拆成多个小 key。
  • 追问:删除大 Key 怎么做? 用 UNLINK 异步删除、分批删除集合元素,避免 DEL 阻塞。

七、加强记忆

热点 Key = 某 key 被极高频访问,请求全挤到存它的单个 Redis 节点,导致该节点被打爆、负载不均、失效时还引发击穿。解法:多级/本地缓存前置拦截(最有效)、热点 key 复制成多副本打散到多节点、读写分离扩从节点、热点探测大 Key = 某 key 的 value 太大(大 String / 百万元素集合),读写会阻塞 Redis 单线程、占满带宽、删除卡顿、内存倾斜。解法:拆分成多个小 key、用 Hash 等合适结构只取所需字段、用 UNLINK 异步删除、--bigkeys 定期排查。核心区分:热点是「访问频率高」,大 key 是「数据体积大」