OBJECT ENCODING 返回 raw 或 embstr 说明字符串对象的底层编码:embstr 表示短且未修改的紧凑编码(≤64 字节),raw 表示已修改或较长,触发了动态扩容。

OBJECT ENCODING 返回 raw 或 embstr 说明什么
Redis 对字符串对象做了两种底层编码优化:embstr 是紧凑的单次内存分配(适合短字符串),raw 是常规的 sds 结构(支持动态扩容)。当 OBJECT ENCODING key 返回 embstr,通常表示该字符串长度 ≤ 44 字节(Redis 7.0 后为 64 字节)且未被修改过;一旦执行过 APPEND、SET 覆盖或 INCR 等操作,就会降级为 raw。
常见误判是看到 raw 就认为“没优化”,其实只要值本身不超限、且没触发过修改,新建的字符串默认仍是 embstr。检查时务必确认操作历史,而不是只看当前返回值。
- 用
DEBUG OBJECT key可看到更详细信息,比如是否 lru、refcount,但生产环境慎用 -
embstr在内存碎片控制和缓存局部性上略优,但对绝大多数业务无感知差异 - 别为强转
embstr做额外操作——Redis 不提供手动编码切换命令
哈希对象返回 ziplist vs hashtable 的实际影响
哈希默认用 ziplist 编码(紧凑、省内存),但满足任一条件就会升级为 hashtable:hash-max-ziplist-entries 超限(默认 512)、hash-max-ziplist-value 超限(默认 64 字节)、任意 field/value 含非二进制安全字符(比如 \x00)。
升级后无法自动降级,即使删到只剩 1 个字段也还是 hashtable。所以如果你批量写入后又大量删除,内存不会回收回 ziplist 模式。
- 查配置:用
CONFIG GET hash-max-ziplist-entries和CONFIG GET hash-max-ziplist-value - 验证编码:先
HLEN key看字段数,再HSTRLEN key field看单个 value 长度,比对配置阈值 - 注意
HSTRLEN是 Redis 4.0+ 才有,旧版本只能用HGET key field | wc -c估算
为什么 OBJECT ENCODING 查集合/有序集合总是返回 intset 或 skiplist
集合(set)用 intset 编码的前提是:所有元素都是整数字符串(如 "123")、元素数量 ≤ set-max-intset-entries(默认 512)。一旦插入 "abc" 或超过阈值,立刻转成 hashtable,且不可逆。
有序集合(zset)同理:zset-max-ziplist-entries 和 zset-max-ziplist-value 控制是否用 ziplist 编码;否则用 skiplist + dict 双结构。注意:Redis 7.0 开始已弃用 ziplist,改用 listpack,但 OBJECT ENCODING 仍显示 ziplist 兼容旧名。
- 判断 intset 是否还生效:用
SMEMBERS key | head -n 1看第一个元素是否为纯数字字符串 - 插入非数字字符串会静默触发转换,没有任何警告
-
skiplist支持 O(log N) 排序查询,ziplist是 O(N),但小数据量下差别可忽略
用 OBJECT ENCODING 诊断性能问题容易忽略的点
这个命令本身开销极小,但它只告诉你“当前编码”,不反映历史变更路径。真正影响性能的,往往是编码切换时的隐式拷贝:比如一个大 ziplist 哈希升级成 hashtable,会一次性 malloc 新空间、遍历迁移全部字段——这可能引发毫秒级卡顿,尤其在主线程中。
线上遇到延迟毛刺,不能只查 OBJECT ENCODING,得结合 SLOWLOG 和 INFO commandstats 看是否有大量 HSET / ZADD 触发了临界点。
- 监控建议:用
redis-cli --stat观察used_memory_human突增,再定位对应 key - 不要在热 key 上反复做
HSET+HDEL组合操作,容易在边界值附近反复触发编码切换 -
OBJECT ENCODING对 Lua 脚本内 key 无效——脚本里没法调这个命令










