性能测试面试中,关于redis最爱问的两个问题——什么是大Key(Big Key)和热Key(Hot Key)
📅 2026/7/18 5:40:05
👁️ 阅读次数
📝 编程学习
在Redis的性能保障体系中,大Key(Big Key)和热Key(Hot Key)是两个最核心的“定时炸弹”。它们虽然都可能导致系统卡顿甚至崩溃,但成因、危害和治理思路完全不同。
简单来说:
- 大Key 是“体积问题”:单个Key太大,导致网络阻塞、内存不均、删除卡顿。
- 热Key 是“流量问题”:单个Key访问太频繁,导致单节点过载、带宽打满。
下面为你详细拆解:
什么是大Key?
定义
指单个Key的Value过大或集合类型元素过多的Key。业界通常参考以下阈值:
| 数据类型 | 大Key 警戒线 | 危险线 |
|---|---|---|
| String | > 10 KB | > 1 MB |
| Hash / Set / ZSet | 元素 > 5000个 | 元素 > 1万 或 Value总量 > 1MB |
| List | 长度 > 5000 | 长度 > 1万 |
注意:阈值不是绝对的,取决于业务场景和网络带宽。核心原则是:单次操作耗时是否超过1ms。
危害
- 阻塞主线程:Redis是单线程模型,
DEL一个大Key可能耗时数百毫秒,期间所有请求被阻塞。 - 网络拥塞:读取一个1MB的Value,在千兆网卡下仅传输就要8ms,高并发时直接打满带宽。
- 集群数据倾斜:大Key所在分片内存远高于其他节点,例如某 Slot 因大 Key 占用 80% 节点内存,其他 Slot 的 Key 被频繁淘汰,缓存命中率暴跌。
- 慢查询雪崩:
HGETALL、SMEMBERS等全量操作触发慢日志,连锁影响上游服务RT。 - 过期删除卡顿:惰性删除+定期删除机制下,大Key过期时的清理动作会阻塞服务。
常见产生场景
- 把整个列表/大JSON存入一个String(如文章全文、用户行为流水)
- Hash存储了数万条记录却只用
HGETALL读取 - 排行榜ZSet无限增长未做截断
- 缓存了未压缩的大对象
注意:大 Key 不等于内存泄漏
大 Key 是“合法但危险的数据”,内存泄漏是“无法回收的垃圾内存”。
| 维度 | 大 Key 问题 | 内存泄漏 |
|---|---|---|
| 本质 | 数据确实存在且被引用,只是体积过大 | 内存已无引用但未被释放,永远无法使用 |
| 能否通过 DEL/UNLINK 解决 | 能,删除后内存立即回收 | 不能,因为程序找不到这块内存了 |
| 监控表现 | MEMORY USAGE <key>能明确看到占用 | INFO memory显示 used_memory 持续增长,但DBSIZE和已知 Key 总量对不上 |
| 治理方式 | 拆分、压缩、异步删除 | 升级版本、修复代码、重启节点 |
什么是热Key?
定义
指单位时间内被极高频率访问的Key。判断标准通常是:
- 单Key QPS > 1万~5万(取决于Value大小和节点性能)
- 某Key访问量占集群总QPS的10%以上
危害
- 单节点过载:Redis Cluster按Slot分片,热Key固定在某个节点,该节点CPU/网络先被打满,而其他节点空闲。
- 带宽瓶颈:即使Value只有1KB,5万QPS也需要约400Mbps带宽,极易触顶。
- 级联故障:热Key节点响应变慢 → 上游超时重试 → 流量翻倍 → 节点彻底宕机 → 请求穿透到DB。
- 扩容无效:因为热Key只在一个Slot上,加节点无法分散压力。
常见产生场景
- 秒杀商品库存:百万人抢同一个SKU
- 爆款内容:热搜话题、明星八卦、病毒式传播的文章
- 全局配置/计数器:所有请求都要读的开关、全局自增ID
- 爬虫/刷接口:恶意高频访问特定接口
- 缓存击穿:热点Key过期瞬间,大量请求同时打到DB并回写
大Key vs 热Key 对比总结
| 维度 | 大Key | 热Key |
|---|---|---|
| 本质 | 空间问题(Volume) | 时间问题(Velocity) |
| 发现难度 | 较易(离线扫描/RDB分析) | 较难(需实时采样/业务感知) |
| 监控指标 | Memory Usage, Slow Log | QPS per Key, Node CPU/Bandwidth |
| 治理核心 | 拆分 + 压缩 + 异步删除 | 多级缓存 + 读写分离 + 限流 |
| 能否通过扩容解决 | 可以(迁移大Key到新节点) | 不能(热Key仍在原节点) |
| 典型工具 | redis-cli --bigkeys, RDB Analyzer | Tair热点探测, Proxy层统计, 客户端埋点 |
治理方案速查
大Key治理
- 拆分:Hash按业务字段拆成多个小Hash;List/ZSet分页存储
- 压缩:Value使用Snappy/LZ4压缩后再存入
- 异步删除:用
UNLINK代替DEL(Redis 4.0+),后台线程释放内存 - 避免全量操作:禁止
HGETALL/SMEMBERS,改用HSCAN/SSCAN游标遍历 - 设置合理TTL:防止无限增长,定期归档冷数据
热Key治理
- 本地缓存(L1 Cache):JVM内Caffeine/Guava缓存,毫秒级响应,零网络开销
- 多副本分散:将热Key复制N份(如
item:123:replica:0~9),读请求随机路由 - 读写分离:从节点分担读压力(注意主从延迟)
- Proxy层拦截:在Twemproxy/Codis/Tair Proxy层识别热Key并缓存
- 限流降级:Sentinel对热Key接口限流,保护后端
- 永不过期+异步刷新:逻辑过期,后台线程定时更新,避免击穿
面试加分点
“在实际工作中,大Key和热Key经常叠加出现——比如一个爆款商品的详情页既是大Key(包含图文+评论摘要)又是热Key。这时需要组合拳:先拆分压缩解决大Key问题,再加本地缓存+多副本解决热Key问题。单纯靠Redis自身优化是不够的,必须结合应用层架构设计。
编程学习
技术分享
实战经验