MEMORY USAGE命令能查出单个key当前占用的近似内存字节数,对string最准确;不能查key自身开销、底层编码细节,不支持通配符或批量查询,且多次执行结果可能因内存分配器行为和编码预分配而不同。
MEMORY USAGE命令能查出什么,不能查什么
MEMORY USAGE 只返回单个 key 当前占用的近似内存字节数,不区分底层编码(比如 list 是用 ziplist 还是 linkedlist),也不包含 key 本身的开销(如 dictEntry 指针、过期时间字段等)。它对 string 最准确;对 hash/set/zset/list,结果依赖于实际编码和元素数量,但仍是诊断大 key 的最快入口。
常见错误现象:MEMORY USAGE non_existent_key 返回 (integer) 0,不是报错,容易误判为“存在但很小”;MEMORY USAGE 不支持通配符或批量 key,必须逐个调用。
怎么对特定数据类型做精细化内存探查
先用 TYPE 确认类型,再结合 DEBUG OBJECT(仅开发/测试环境)或 MEMORY USAGE + 类型相关命令交叉验证:
-
string:直接MEMORY USAGE key_name即可,结果基本等于值长度 + 少量元数据 -
hash:先HLEN key_name看字段数,再MEMORY USAGE key_name;若值很大但字段少,可能是单个 field value 超长 -
zset:用ZCARD key_name和ZRANGE key_name 0 0 WITHSCORES抽样看 score 和 member 长度,MEMORY USAGE结果会随 member 数量非线性增长 -
list:LLEN key_name后对比MEMORY USAGE,若比预期高很多,大概率是用了linkedlist编码(每个 node 额外约 64 字节)
生产环境慎用的替代方案与参数技巧
DEBUG OBJECT 能看到编码类型、refcount、lru 等,但会阻塞主线程,线上禁止使用。更安全的做法是:
- 用
redis-cli --bigkeys快速扫描全库大 key(按类型分组统计,但不精确到字节) - 开启
INFO memory中的mem_clients_normal/mem_clients_slave辅助判断客户端连接内存占比 -
MEMORY USAGE支持samples参数(Redis 4.0+),例如MEMORY USAGE key_name SAMPLES 10,对集合类会采样部分元素估算,减少误差但不改变本质——它仍不揭示编码细节
注意:SAMPLES 对 string 无效;采样数过大可能短暂影响响应延迟。
为什么同一个 key 多次执行 MEMORY USAGE 结果不同
omegafw.gmcwatch.cn
rolexfw.gmcwatch.cn
patekfw.gmcwatch.cn
omegafw.swatchsh.com
rolexfw.swatchsh.com
patekfw.swatchsh.com
omegafw.paydyj.com
rolexfw.paydyj.com
patekfw.paydyj.com
omegafw.watchku.com
rolexfw.watchku.com
patekfw.watchku.com
omegafw.gmcwatch.cn
rolexfw.gmcwatch.cn
patekfw.sitezj.cn
Redis 内存分配器(如 jemalloc)有碎片和页对齐行为,且某些编码会在 resize 时预分配空间(比如 dict 扩容后未立即缩容)。更关键的是:MEMORY USAGE 统计的是当前分配给该 key 的总内存,包括尚未使用的预留空间。
典型场景:
- 刚
HSET1000 个字段后立刻查,结果偏高;等几秒再查可能略降(后台渐进式 rehash 或惰性释放) - 频繁
ZADD/ZREM后,zset的skiplist层高和指针数组可能残留冗余内存 -
list从ziplist编码升级为quicklist后,即使删到只剩几个元素,也不会自动降级回ziplist
所以单次 MEMORY USAGE 值只能作相对参考,趋势比绝对值更有意义。