redis-cli --bigkeys仅用于快速摸底,输出每种类型“逻辑最大”的Key(如元素数或字符串长度),不反映真实内存占用,易漏判异常大Key,需配合MEMORY USAGE精准验证。

redis-cli --bigkeys 只能摸底,不能当结论用
它抽样扫描,输出的是每种类型里“看起来最大”的那个 key,比如 HGETALL 耗时最长的 hash、LRANGE 元素最多的 list。但真实拖垮 Redis 的大 key,可能藏在没被抽到的 95% 里——尤其当你的 key pattern 偏离常规(比如 taotoken:log:20261001:uid_* 这类带日期和 UID 的),抽样容易漏掉单日爆涨的异常 key。
执行时必须加 -i 参数控速,否则高频 TYPE + STRLEN/LLEN 会把 CPU 打满。建议从 -i 0.1 起手,观察 slowlog 是否新增 SCAN 相关条目;若仍有抖动,调高到 -i 0.5。
- 别在高峰期跑,哪怕加了
-i,它仍会持续发命令,影响 P99 延迟 - 结果里只显示“最大”,不显示“第几大”。一个
cart:user:10086占 80MB,另一个同类型只占 12MB,后者不会出现在报告里,但它照样能卡住主线程 - 集群模式下,
--bigkeys默认只扫当前连接的节点,得手动轮询所有 master 节点
用 SCAN + MEMORY USAGE 精准定位单个可疑 key
当你已经从 slowlog 里看到大量 HGETALL、SMEMBERS、LRANGE 耗时 >100ms,说明问题 key 已经暴露在命令层。这时候该用游标扫描,逐个测内存占用:
redis-cli -h 127.0.0.1 -p 6379 -a your_pass --scan --pattern "taotoken:*" | head -n 1000 | xargs -I {} sh -c 'echo {}; redis-cli -h 127.0.0.1 -p 6379 -a your_pass memory usage {} 2>/dev/null || echo "ERR"' | awk 'NF==2 && $2 > 1048576 {print $0}'
这段命令干三件事:按前缀扫 key、对每个 key 调 MEMORY USAGE、筛出超 1MB 的。注意:MEMORY USAGE 是 O(1) 的,不阻塞,但频繁调用仍需控制节奏——上面用 head -n 1000 限流,实际可配合 sleep 0.01 插入延时。
-
MEMORY USAGE返回的是近似值,包含 key 名、value、内部结构开销,比STRLEN或LLEN更真实反映内存压力 - 如果返回
(error) ERR unknown command `memory`,说明 Redis 版本 DEBUG OBJECT(不推荐,生产禁用)或改用redis-rdb-tools离线分析 RDB 文件 - 别直接用
KEYS,它会阻塞整个实例,SCAN是唯一安全的选择
slowlog 查看卡顿源头,反向锁定 key 名
Redis 卡顿时,真正要盯的是 slowlog,不是监控图上的平均 CPU。一条 HGETALL cart:user:10086 耗时 680ms,就能让后面 2000+ 请求排队。先确认 slowlog 阈值是否合理:
redis-cli config get slowlog-log-slower-than —— 如果是 10000(即 10s),那 200ms 的卡顿根本不会记录。建议设为 100000(100ms),再查最近 20 条:redis-cli slowlog get 20
- 重点关注耗时列(第三字段)>100000(单位微秒)、命令列含
HGETALL/SMEMBERS/DEL的条目 - 第二字段是时间戳,结合业务日志里的报错时间,能快速圈定是哪个 key 在作祟
- 如果 slowlog 为空,但延迟明显,说明卡顿来自大 key 的过期删除(惰性+定期删除机制触发),此时要查
INFO stats里的expired_keys和evicted_keys是否突增
集群环境下大 key 导致数据倾斜,光删没用
发现 taotoken:session:shard_7:* 下某个 key 占了 32MB,删掉它确实能缓解,但下次还可能在同一个 slot 里长出来。因为 Redis Cluster 按 key 的 CRC16 值分片,taotoken:session:shard_7:user_123 和 taotoken:session:shard_7:user_456 必然落在同一节点——这是设计使然,不是 bug。
真正要做的不是“删”,而是“拆”:把单个大 hash 拆成多个小 hash,比如按用户行为类型分:taotoken:session:shard_7:user_123:click、taotoken:session:shard_7:user_123:search。这样既分散了单 key 容量,又避免了单 slot 内存打满后扩容无效的问题。
- 拆分逻辑必须双写过渡:新逻辑写多 key,旧逻辑仍读原大 key,等存量数据自然过期后再下线旧路径
- 不要用
RENAME或MOVE搬大 key,它们都是原子操作,一样会阻塞 - 如果已出现主从延迟飙升,优先停写,用
CLIENT LIST查看qbuf(查询缓冲区)是否堆积,确认是否是大 key 同步拖慢了 replica
大 key 的危害从来不在“有多大”,而在“什么时候被碰”。一次 HGETALL、一次 DEL、一次过期清理,都可能成为压垮 Redis 的最后一根稻草。排查时盯着 slowlog 和 MEMORY USAGE,治理时重心放在拆分而非删除,这才是线上系统能扛住流量变化的关键。











