redis 7.0 中 hash 使用 listpack 的触发条件是:字段数 ≤ hash-max-listpack-entries(默认512)且所有 field 和 value 长度 ≤ hash-max-listpack-value(默认64),二者必须同时满足,否则升级为 hashtable。

Redis 7.0 中 Hash 使用 listpack 的触发条件
Redis 7.0 已完全弃用 ziplist,改用更安全、更易维护的 listpack 作为小 Hash 的紧凑编码。是否启用 listpack 取决于两个运行时阈值,且必须**同时满足**:
-
hash-max-listpack-entries:字段对(field-value)总数 ≤ 该值(默认512) -
hash-max-listpack-value:每个 field 和每个 value 的字符串长度都 ≤ 该值(默认64)
注意:listpack 是只读优化结构,一旦执行 HSET 修改任意字段值(哪怕只是追加一个字符),只要新值超长或总数量超标,整个 Hash 就会**不可逆地升级为 hashtable**。所以别指望“改小一点再切回去”。
List 和 ZSet 的 listpack 阈值配置差异
虽然 listpack 同时用于 List 和 ZSet 的紧凑存储,但它们的控制参数名和默认值不同,容易混淆:
- List 不再有独立的 listpack 阈值——它底层统一是
quicklist,而quicklist内部的每个节点才是listpack;真正控制单个listpack大小的是list-max-listpack-size(Redis 7.0+ 新增,旧版叫list-max-ziplist-size),默认值为-2(表示每个listpack最多存 8KB 数据) - ZSet 的 listpack 触发由两个独立参数控制:
zset-max-listpack-entries(默认128)和zset-max-listpack-value(默认64),含义与 Hash 类似,但阈值更保守——ZSet 对查询性能更敏感,所以更早退化到skiplist + dict
修改时务必确认命令拼写:zset-max-listpack-value 不能写成 zset-max-ziplist-value,后者在 Redis 7.0+ 已被忽略且不会报错,只会静默失效。
如何实时验证当前 key 的实际编码类型
光改配置没用,得确认你的数据真走到了 listpack 路径上。最直接的方法是用 OBJECT ENCODING 命令:
Redis 缓存和数据结构管理技能。通过自然语言操作 Redis,支持 String、Hash、List、Set、ZSet、Stream 等数据结构操作。当用户提到 Redis、缓存、消息队列、会话存储时使用此技能。
127.0.0.1:6379> HSET myhash f1 "a" f2 "bb" f3 "ccc" (integer) 3 127.0.0.1:6379> OBJECT ENCODING myhash "listpack"
常见返回值含义:
-
"listpack":当前处于紧凑编码(Redis 7.0+) -
"hashtable":已升级,无法降级 -
"quicklist":List 类型的统一编码,不代表内部一定是 listpack(需结合DEBUG OBJECT看节点细节) -
"skiplist":ZSet 已退化,说明至少有一个 member 超过zset-max-listpack-value或总数量超限
注意:OBJECT ENCODING 返回的是顶层结构类型,不是内存布局快照。如果刚插入一个大 value 导致升级,它立刻返回 "hashtable",但旧数据还在原内存块里,直到下次写操作才真正迁移。
配置修改后不生效的三个高频原因
改了 redis.conf 却发现数据还是 hashtable?大概率卡在这三处:
- 配置项写错命名:Redis 7.0+ 所有 listpack 相关参数都带
-listpack-,如hash-max-listpack-entries;保留的-ziplist-形式参数(如hash-max-ziplist-entries)**完全无效**,但 Redis 不报错也不警告 - 未重启或未
CONFIG REWRITE:仅CONFIG SET是临时生效,进程重启后还原;若用CONFIG SET修改,记得后续执行CONFIG REWRITE持久化到配置文件,否则下次启动仍按旧值加载 - 已有 key 不受新配置影响:阈值只作用于**新创建或新写入的 key**。一个已存在且是
hashtable编码的 Hash,无论你怎么调低hash-max-listpack-entries,它都不会自动缩回listpack—— 这是设计使然,不是 bug
真正要压测效果,得清空 DB 或用全新 key 重跑数据流,别拿老 key 测新配置。










