不能。redis-cli --bigkeys 仅抽样扫描,估算五类结构的元素数或字节数,不区分业务语义,存在误判、漏检和非真实内存反映等问题。

redis-cli --bigkeys 能直接找出所有大Key吗
不能。它只做抽样扫描,不是全量遍历,结果是估算值,且默认只统计 string、list、set、hash、zset 五类结构的「元素数量」或「序列化长度」,不区分业务语义。
常见误判场景:
- 一个
hash有 5000 个字段但每个值都是空字符串,--bigkeys会标为“big hash”,实际内存占用极小 - 一个
string值是 1MB 的 base64 图片,但--bigkeys只按字节数报 size,不提示类型风险 - 扫描期间新写入的 key 不会被覆盖采样,可能漏掉正在膨胀的热 key
实操建议:
- 在低峰期运行:
redis-cli -h <code>host-pport--bigkeys,避免阻塞主线程 - 加
-i 0.01参数降低采样间隔(默认 0.01 秒),减少对线上影响 - 配合
INFO memory看used_memory_peak_human,确认是否存在持续增长的大 key
怎么判断一个 key 算“真大”而不是抽样噪声
单靠 --bigkeys 输出的 “Largest string value found” 或 “Biggest hash” 没法下结论,必须人工验证。
验证步骤:
- 从
--bigkeys输出中复制疑似 key 名,用MEMORY USAGE <code>key_name查真实内存占用(Redis 4.0+) - 对非
string类型,用对应命令看结构规模:如HLEN <code>key_name、LLEN <code>key_name、SCARD <code>key_name - 用
OBJECT ENCODING <code>key_name看底层编码(比如hash是hashtable还是ziplist),编码切换点会影响内存和性能
注意:MEMORY USAGE 返回的是近似值,含 key 名、过期时间、内部结构开销等,比纯 value 大 10%~30% 属正常。
优化大 Key 时为什么不能直接 DEL
DEL 是阻塞操作,如果 key 对应的底层结构特别大(比如千万级 zset),删除可能卡住主线程几百毫秒甚至秒级,引发超时雪崩。
安全删除方案:
- 对
hash/zset/set:用HSCAN/ZSCAN/SSCAN分批获取并HDEL/ZREM,每次不超过 1000 个元素 - 对超大
string:先RENAME成临时名,再用后台脚本分块GETRANGE+ 丢弃,最后DEL - 对带过期时间的 key:确认是否真要删,有时只是 TTL 设置过长,改用
EXPIRE缩短更稳妥
别依赖 UNLINK 万能解——它虽异步,但释放内存仍需后台线程参与,若系统内存已紧张,反而加剧延迟。
如何预防新大 Key 写入
靠事后扫描永远滞后。关键是在写入侧设防:
- 在客户端 SDK 封装写入逻辑,对 value 长度或集合 size 做前置校验(例如拒绝 >512KB 的
SET) - 用 Redis 的
CONFIG SET maxmemory-policy noeviction配合监控告警,避免 LRU 淘汰掩盖大 key 问题 - 对必须存大结构的场景(如用户消息列表),强制分片:把
user:123:msgs拆成user:123:msgs:0~user:123:msgs:9,用hash_tag控制分片键
最容易被忽略的一点:很多大 key 来自日志类缓存(如 log:202405:user_login),这类 key 应该用 EXPIREAT 绑定绝对过期时间,而不是靠人工清理。










