Redis Hot Key 与 Big Key:危害、发现与解决方案

在 Redis 面试中,Hot Key 和 Big Key 是两个非常高频的问题。

它们的名字很像,但解决的问题完全不同:

Hot Key:一个 Key 被访问得太频繁。 Big Key:一个 Key 对应的数据结构太大。

需要特别注意,Big Key 并不是说 Key 字符串本身很长,而是这个 Key 对应的 Value 数据结构包含了大量数据。

下面分别从危害、发现、解决三个方面来看。


一、Hot Key

1. Hot Key 有什么危害?

假设电商平台有一个商品:

复制代码
product:1001

平时每秒只有几十次访问。

但某天这个商品突然上了热搜,访问量暴涨到:

复制代码
product:1001 → 50000 QPS

这就形成了 Hot Key。

如果使用 Redis Cluster

复制代码
Node1
Node2
Node3  ← product:1001
Node4
Node5
Node6

由于同一个 Key 始终会映射到固定的 Hash Slot,因此大量请求都会集中到 Node3。

最终可能出现:

复制代码
50000 QPS
    ↓
product:1001
    ↓
Node3 压力暴增
    ↓
CPU / 网络 / Redis 延迟升高
    ↓
请求超时

所以 Hot Key 最大的问题不是"Redis 总体 QPS 太高",而是:

访问压力过于集中,可能把某一个 Redis 节点打成瓶颈。


2. 如何发现 Hot Key?

通常分两步。

第一步,看 Redis 节点是否存在异常。

例如监控发现:

复制代码
Node1:2000 QPS
Node2:2200 QPS
Node3:50000 QPS ← 异常
Node4:2100 QPS

同时 Node3 的 CPU、网络流量、命令延迟明显升高。

这时候就应该怀疑是否存在 Hot Key。

第二步,进一步定位具体 Key。

可以使用:

复制代码
redis-cli --hotkeys

也可以在应用层统一封装 Redis Client,对访问进行采样统计:

复制代码
Redis Client
    ↓
记录 Key / 命令 / 次数
    ↓
统计 Top N
    ↓
找到访问量最高的 Key

不过生产环境不要简单地把完整 Key 直接作为 Prometheus Label:

复制代码
redis_get_total{key="user:100001"}
redis_get_total{key="user:100002"}
redis_get_total{key="user:100003"}

如果用户 ID 有几百万个,就会产生严重的高基数问题。

更合理的是使用 Key Pattern、采样或者单独的 Top N 分析系统。


3. Hot Key 怎么解决?

还是刚才的商品案例:

复制代码
product:1001 → 50000 QPS

方案一:本地缓存

如果商品信息短时间内不经常变化,可以在应用进程增加本地缓存:

复制代码
请求
 ↓
本地缓存
 ↓ miss
Redis
 ↓ miss
MySQL

第一次请求从 Redis 获取数据,之后一段时间内直接从本地缓存返回。

原本:

复制代码
50000 QPS → Redis

可能变成:

复制代码
50000 QPS
    ↓
本地缓存拦截
    ↓
几百 QPS → Redis

这样可以直接减少 Redis 的访问压力。


方案二:Key 分片

如果业务允许,可以把一个 Hot Key 拆成多个 Key:

复制代码
product:1001:0
product:1001:1
product:1001:2
product:1001:3

让请求分散访问这些 Key,从而降低单个 Redis 节点的压力。

不过这种方案会增加数据一致性和读取逻辑的复杂度,不能为了分片而盲目分片。


二、Big Key

1. Big Key 有什么危害?

例如用户 Feed 系统:

复制代码
feed:user:10086

这个 Key 对应一个拥有 300 万个元素的 List

这里真正"大"的不是:

复制代码
feed:user:10086

这个字符串,而是它对应的 Redis 数据结构。

Big Key 会带来几个问题。

第一,内存占用大。

一个 Key 就可能占用几十 MB 甚至几百 MB,导致 Redis 内存压力增加。

第二,读写操作成本高。

例如:

复制代码
LRANGE feed:user:10086 0 -1

如果一次读取几百万条数据,不仅 Redis 需要处理大量数据,网络也需要传输大量内容。

第三,大 Key 删除可能造成 Redis 延迟抖动。

例如:

复制代码
DEL feed:user:10086

如果这个 Key 非常大,删除过程中可能消耗较多 CPU,影响 Redis 主线程处理其他请求。

因此 Big Key 的核心危害可以概括为:

一个 Key 携带的数据太多,会增加内存、CPU、网络以及大规模读写操作的成本。


2. 如何发现 Big Key?

可以先使用:

复制代码
redis-cli --bigkeys

对 Redis 中的数据结构进行扫描,找出比较大的 Key。

找到可疑 Key 后,可以进一步使用:

复制代码
MEMORY USAGE feed:user:10086

查看它实际占用的内存。

线上也可以定期执行:

复制代码
SCAN
  ↓
逐步遍历 Key
  ↓
MEMORY USAGE
  ↓
统计 Top N
  ↓
告警

这里要注意:

不要使用 KEYS * 做线上大规模扫描。

因为 KEYS 需要一次性遍历大量 Key,可能阻塞 Redis。


3. Big Key 怎么解决?

继续使用刚才的 Feed 案例。

原来:

复制代码
feed:user:10086
    ↓
300 万条数据

方案一:拆分数据

可以按照时间进行拆分:

复制代码
feed:user:10086:202609
feed:user:10086:202608
feed:user:10086:202607

或者按照业务维度进行拆分。

核心思想就是:

不要让所有数据集中在一个 Redis Key 中。


方案二:避免一次读取全部数据

不要:

复制代码
LRANGE key 0 -1

一次性读取全部数据。

而应该分页:

复制代码
LRANGE key 0 49
LRANGE key 50 99

让单次 Redis 操作处理的数据量保持在合理范围。


如果确定需要删除一个非常大的 Key,可以考虑:

复制代码
UNLINK feed:user:10086

相比直接 DELUNLINK 会尽可能把实际内存释放放到后台线程处理,从而降低删除操作对 Redis 主线程的影响。


三、Hot Key 和 Big Key 怎么区分?

可以用一句话记:

复制代码
Redis Key
                     ↓
          ┌──────────┴──────────┐
          ↓                     ↓
      访问次数太多           数据量太大
          ↓                     ↓
       Hot Key              Big Key
          ↓                     ↓
     流量过于集中          操作成本过高

所以:

Hot Key 看"谁访问得多",Big Key 看"谁肚子里的东西多"。

两者甚至可以同时出现。

例如:

复制代码
product:1001

既保存了一个非常大的商品推荐数据结构,同时又是一个爆款商品,被大量用户访问。

那么它既是:

复制代码
Hot Key + Big Key

这种 Key 就需要重点治理。


四、面试时怎么回答?

如果面试官问:

"Redis 的 Hot Key 和 Big Key 有什么问题?怎么解决?"

可以直接回答:

Hot Key 是某个 Key 被大量请求集中访问,主要问题是流量集中到某个 Redis 节点,导致该节点 CPU、网络和延迟升高。发现 Hot Key 可以结合 Redis 节点监控以及 redis-cli --hotkeys 或应用层访问统计进行定位。解决上可以使用本地缓存、Key 分片等方式分散访问压力。
Big Key 严格来说不是 Key 字符串大,而是 Key 对应的数据结构过大。它会增加 Redis 的内存、CPU、网络以及大规模读写和删除操作的成本。可以使用 redis-cli --bigkeysMEMORY USAGE 等方式发现,解决上主要是拆分数据、避免一次读取大量数据,以及删除时使用 UNLINK

这就形成了完整的面试逻辑:

是什么 → 为什么危险 → 怎么发现 → 怎么解决。

而不是只背两个定义。

相关推荐
杨云龙UP1 小时前
DB2 HADR 主备架构活动日志参数优化操作手册
linux·运维·服务器·数据库·db2·db2 hadr·日志参数调整
学渣超1 小时前
从一次早高峰数据库告警说起:你真的理解缓存该如何落地应用吗?
redis·后端·架构
我是大猴子1 小时前
MyBatis‑Plus & MyBatis‑Flex 区别
java·服务器·数据库
鸽芷咕2 小时前
SQL Server数据库迁移避坑指南:老代码不用重写,金仓KES V9R4C019把路铺平了
数据库
鸽芷咕2 小时前
MongoDB 鸿蒙 PC 适配全记录:从 Bazel 交叉编译到 HNP 原生数据库服务
数据库·mongodb·harmonyos
YangYang9YangYan2 小时前
2026 校招管理会计 JD 拆解,数据分析能力要求与工具清单
java·数据库·数据分析
零依赖极客2 小时前
Day 9·1 KV 也量化——q8 KV 把缓存与 decode 带宽压到一半
c语言·开发语言·arm开发·人工智能·缓存·矩阵
敲代码的嘎仔2 小时前
互动问答系统实战:两级评论模型、ES 搜索集成、Caffeine 多级缓存全记录
java·开发语言·数据库·elasticsearch·缓存·mybatis·高并发
倔强的石头_2 小时前
SQL Server数据库迁移,为什么 KES V9R4C019 能把改代码变成改连接
数据库