Redis 探究:压缩列表 ziplist

ziplist 的组成结构

为了节约内存,Redis 开发了 ziplist 数据结构。一个压缩列表包含任意多个节点entry,每个entry 可以保存1个字节数组,或1个整数值。
ziplist 组成结构

  • zlbytes:整个压缩列表占用的字节数;
  • zltail:尾节点相对列表起始地址的偏移量,等于 尾节点起始地址 - 压缩列表起始地址;
  • zllen:节点 entry 的个数,当列表节点总数大于 65535 时,及超过2字节能表示的最大值时,需要遍历整个列表才能算出真实数量;
  • entry:列表节点,长度不定,由节点保存的内容决定;
  • zlend:特殊值 0xFF 用于标记列表的末尾,相当与 C 语言用 ‘\0’ 表示字符串的结束符。

entry 的构成

压缩列表的节点由 previous_entry_length、encoding、content 三部分构成。
压缩列表节点构成

  • previous_entry_length:记录前一个节点的长度。可以是 1字节 也可以是 5字节(类似 DB 中的 VARCHAR)。如果前一节点长度小于 254 字节,就是 1 字节;否则为 5 字节;
    前一节点长度大于 254 字节时的格式
  • encoding:表示 content 所保存的数据类型(字节数组 或 整数)及长度。最高位以 00、01、10 开头,表示字节数组以 11 开头表示整数编代码,具体见下面两图:
    字节数组编码格式
    整数编码格式

连锁更新

由于每个节点的 previous_entry_length 保存的是前一个节点的长度,如果前一个节点长度小于 254 时,previous_entry_length 占用 1 字节,否则使用 5 字节。

假如列表中 entry 长度均为 253,现在要插入一个长度为 256 的节点 entryX,这时保存 entryX 的 previous_entry_length 不能用1字节了,需要扩展到 5 字节。相应的后续 entry 里的 previous_entry_length 长度均要升级。这就叫做连锁更新,实际上,在删除节点时也可能遇到。

连锁更新,在最坏情况下要对 ziplist 进行 N次空间重分配操作,每次空间重分配最坏的复杂度为 O(N) ,所以连锁更新最坏的复杂度为 O(N^2)。但现实中遇到该情况的概率非常低,ziplistPush 等命令的平均复杂度为 O(N)

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值