在 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 操作处理的数据量保持在合理范围。
方案三:删除时使用 UNLINK
如果确定需要删除一个非常大的 Key,可以考虑:
UNLINK feed:user:10086
相比直接 DEL,UNLINK 会尽可能把实际内存释放放到后台线程处理,从而降低删除操作对 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 --bigkeys、MEMORY USAGE等方式发现,解决上主要是拆分数据、避免一次读取大量数据,以及删除时使用UNLINK。
这就形成了完整的面试逻辑:
是什么 → 为什么危险 → 怎么发现 → 怎么解决。
而不是只背两个定义。