Redis 大 key 问题解决方案
在 Redis 中遇到“大 key”问题(即某个 key 对应的数据结构过大,可能是字符串过长、hash/列表/集合中元素过多等)时,会带来严重的性能问题,比如:
- 阻塞主线程(Redis 是单线程的);
- 复制开销大(主从同步耗时高);
- 慢日志、阻塞客户端;
- 内存碎片或爆内存。
一、如何识别大 key
可以用以下方式排查:
MEMORY USAGE key
查看 key 占用的内存。SCAN
+TYPE
+MEMORY USAGE
脚本遍历判断哪些 key 是大 key。- 使用
redis-cli --bigkeys
工具,扫描整个 Redis 找出最大 key。 - 使用监控工具(如 RedisInsight、Datadog)分析内存占用和慢查询。
二、应对大 key 的解决方案
1. 拆分大 key
把一个大 key 拆成多个小 key,按规则命名,例如:
- 原始:
user:123:friends
(有10万好友) - 拆分后:
user:123:friends:0 user:123:friends:1 ... user:123:friends:99
每个 key 存 1000 个元素。读取时按页组合读取。
2. 分页访问
对于 list/set/zset/hash 结构,分页读取避免一次取完:
- list/zset:用
LRANGE
/ZRANGE
分段。 - hash:用
HSCAN
。 - set:用
SSCAN
。
3. 避免一次性删除大 key
直接 DEL
大 key 会阻塞主线程。可以改用:
- 异步删除:Redis 4.0+ 支持
UNLINK key
,会异步释放内存; - 分批删除:拆成多个小 key,用脚本或程序定期删除。
4. 合理设计数据结构
比如:
- 不要存超长字符串;
- 对于大 hash,可以按子业务拆分多个 hash;
- 考虑是否适合 Redis,超大数据是否应存在其他数据库(如 Elastic、Mongo、Postgres)。
5. 开启 Lazy-free 模式
配置 Redis(4.0+)支持后台异步删除:
lazyfree-lazy-eviction yes
lazyfree-lazy-expire yes
lazyfree-lazy-server-del yes
6. 使用 TTL 控制过期
设置合适的过期时间,避免数据堆积成大 key。
三、补充建议
- 定期巡检:每天自动扫描大 key 预警。
- 监控慢查询和阻塞事件,及时定位问题。
- 开发规范控制数据写入,避免突发写入形成大 key。