redis-cli --bigkeys 设计为每种类型仅报告当前扫描到的最大key,非漏报而是只维护top 1;它统计元素数或字符串长度,不反映真实内存占用,需配合memory usage人工验证。

redis-cli --bigkeys 为什么只报“最大”不报“所有大Key”
它不是漏报,是设计如此:redis-cli --bigkeys 的本质是「每种数据类型只保留一个当前扫描到的最大值」,边 scan 边覆盖。比如 hash 类型,遇到第 1 个有 1000 字段的 key 就记下,后面哪怕扫到 500 个字段数 >1000 的 hash,也不会输出——它只关心“Top 1”,不关心“Top N”。
常见误判场景:
- 一个
user:profilehash 有 8000 个字段,但 7999 个值为空字符串,--bigkeys仍标为 “Biggest hash”,实际内存可能不到 200KB - 一个
log:bufferlist 有 12000 个元素,但每个只是时间戳字符串(如"1716825600"),总 size 很小,却被当成高风险大 Key
所以它适合快速摸底,不适合精准治理。
如何让 --bigkeys 输出更贴近真实内存占用
默认行为只统计元素个数(list/set/zset/hash)或字节数(string),但真实内存 ≠ value 序列化长度。必须加参数引导它往内存维度靠:
- 加
-i 0.001:降低采样间隔,减少对线上影响,尤其在高峰期可避免SCAN挤占过多 CPU 时间片 - 配合
INFO memory看used_memory_peak_human:如果峰值持续高于日常水位 20% 以上,说明真有大 Key 在长期驻留,不是抽样噪声 - 不依赖输出的 “bytes” 数字:string 类型的 “102400 bytes” 是序列化后长度,实际
MEMORY USAGE可能是 130KB+(含 key 名、过期结构、jemalloc 对齐开销)
真正要确认大小,得人工拿 MEMORY USAGE <code>key_name 补查,别信 --bigkeys 单方面输出。
扫描期间新写入的 key 会被漏掉吗
会。因为 --bigkeys 底层用的是 SCAN 游标遍历,而 SCAN 不保证原子性——它按哈希桶顺序走,过程中新增的 key 若落在尚未扫描的桶里,本次就完全错过。
Redis 缓存和数据结构管理技能。通过自然语言操作 Redis,支持 String、Hash、List、Set、ZSet、Stream 等数据结构操作。当用户提到 Redis、缓存、消息队列、会话存储时使用此技能。
更麻烦的是热 Key 场景:
- 一个订单聚合 key
order:batch:202605正在被高频HINCRBY,每次新增字段都可能进新桶 - 扫描开始时它只有 500 字段,扫到一半涨到 6000,但因游标已跳过对应桶,最终不会出现在输出里
所以不能把 --bigkeys 当成“一次扫描保终身”的工具。高频业务线建议每周低峰期跑一次,再结合慢日志(SLOWLOG GET 10)里是否频繁出现 HGETALL/LRANGE 等命令交叉验证。
替代方案:用 SCAN + MEMORY USAGE 写轻量脚本补全
当需要知道“所有 >512KB 的 key”,又不想引入 rdbtools 或 redis-rdb-cli 这类重型工具时,用 Python + redis-py 最简可行:
import redis
r = redis.Redis(host='localhost', port=6379)
cursor = '0'
while cursor != 0:
cursor, keys = r.scan(cursor=cursor, count=500)
for key in keys:
try:
size = r.memory_usage(key)
if size > 512 * 1024:
print(f"{key} -> {size} bytes")
except redis.exceptions.ResponseError:
continue # 如 key 已过期或类型不支持 MEMORY USAGE
注意点:
-
count=500比默认 10 更稳,避免单次 SCAN 返回太多 key 导致客户端 OOM - 必须包
try/except:某些 key 可能已被删、或类型不支持MEMORY USAGE(如 Redis - 别在生产高峰跑:即使 SCAN 不阻塞,高频
MEMORY USAGE也会抬高instantaneous_ops_per_sec
真正难的不是找出大 Key,而是判断它该拆、该删、还是该换存储——比如一个 8MB 的 article:content string,与其硬拆,不如直接扔进 MongoDB 或 CDN。










