首页/数据/数据库速查/List 编码(listpack / quicklist)
Redis 命令96 条

List 编码(listpack / quicklist)

小 List 用 listpack,超过 list-max-listpack-size(默认 128,正数=元素个数上限)后转为 quicklist 的多节点结构;7.2 起 quicklist 由 listpack 节点构成。

数据库速查数据更新于 2026-10-13

List 编码是什么

Redis 的 List 有两种内部编码:元素少且小的时候用 listpack(紧凑连续内存),超过阈值后转成 quicklist(双向链表,每个节点又是一个 listpack)。7.2 起 quicklist 的节点统一由 listpack 构成,内存效率比早期的 ziplist 更好。需要强调的是编码只影响内存占用与中间位置操作的常数,与头尾操作无关:LPUSH/RPOP 这类操作始终是 O(1)。

基本信息

listpack元素数量与单个元素都小时使用,紧凑连续
quicklist链表 + 节点结构,节点内是 listpack
阈值参数list-max-listpack-size,默认 128(正值表示元素个数上限)
负值含义为负时表示按「单个元素的字节大小」限制,不再是元素个数
观察OBJECT ENCODING key;MEMORY USAGE key 看实际占用

典型使用场景

  • 内存排查:消息队列积压时确认 List 是否已转 quicklist,评估内存水位
  • 容量规划:估算单条 List 最多可容纳多少元素,避免形成超大键
  • 队列长度治理:把超长 List 拆成多段,降低单个键的内存与删除开销
  • 版本升级对比:7.2 前后同一批键的编码与内存差异可作为升级收益依据
  • 参数验证:调整 list-max-listpack-size 后用新建键验证是否按新阈值生效

观察编码

观察编码
# 小列表:listpack
RPUSH small 1 2 3
OBJECT ENCODING small        # -> listpack
# 查看当前阈值(默认 128)
CONFIG GET list-max-listpack-size
# 插入超过阈值后编码会转为 quicklist
RPUSH big $(seq 1 500)
OBJECT ENCODING big          # -> quicklist
# 想知道真实内存占用,别只看编码
MEMORY USAGE big
LLEN big

编码对照

编码结构内存特点头尾操作
listpack单块连续内存,逐个元素紧凑存放最省,无额外指针O(1)
quicklist双向链表,每个节点是一个 listpack节点间有指针开销,按节点分摊O(1)
转换方向单向:listpack 转 quicklist 后不回退——
list-max-listpack-size 的符号决定语义:正数是「每个节点的元素个数上限」,负数是「每个节点的字节上限」。调参数前先在测试实例上验证当前版本的解释方式。
List 的中间位置操作(LINSERT、LINDEX 大下标、LSET 等)在两种编码下都不是 O(1),超大 List 应避免把中间操作放进高频路径。

易错点

  • 以为 quicklist 的节点划分完全由 list-max-listpack-size 决定:单个元素过大时也会影响节点划分,负值参数下更是按字节限制
  • 只看 OBJECT ENCODING 判断内存:编码只是结构,实际占用用 MEMORY USAGE 单键实测
  • 把编码当成性能开关:头尾入队出队与编码无关,编码影响的是内存与中间操作的常数
  • 让 List 无限增长形成超大键:删除或迁移该键时会长时间阻塞单线程,队列应设长度上限或分批消费
  • 调完阈值指望老键自动重编码:已有键不会立刻变化,只在新键或重建键时按当前阈值判断

数据来源与参考

  • Redis 官方文档: OBJECT ENCODING
  • Redis 官方文档: 内存优化(list-max-listpack-size)

相关工具

​‌‌​​‌​​​‌‌​‌‌‌‌​‌‌​​​‌‌​‌‌‌​​‌‌​​‌​‌‌‌​​‌‌‌​​​‌​‌‌​‌​​‌​‌‌‌​​​‌​‌‌​‌​​‌​‌‌​​​‌‌​‌‌‌​‌​​​‌‌​‌‌‌‌​​‌​‌‌‌​​‌‌​​​‌‌​‌‌​‌‌‌‌​‌‌​‌‌​‌