Redis-6. 压缩列表

压缩列表

压缩列表(ziplist)是列表键和哈希键的底层实现之一。
当一个列表键只包含少量列表项,且每个列表项是小整数值或者长度较短的字符串时,Redis就会使用压缩列表来做列表键的底层实现

当一个哈希键只包含少量键值对,且每个键值对的键和值是小整数值或者长度较短的字符串时,Redis使用压缩列表来做哈希键的底层实现

压缩列表的构成

压缩列表是为了节约内存开发的,是由一系列特殊编码的连续内存块组成的顺序型数据结构。
一个压缩列表可以包含任意多个节点(entry),每个节点可以保存一个字节数组或者一个整数值

压缩列表的各个组成部分:

属性类型长度用途
zlbytesuint32_t4字节记录整个压缩列表占用的内存字节数。对压缩列表内存重分配或者计算zlend的位置时使用
zltailuint32_t4字节记录表尾节点距离起始地址有多少个字节
zllenuint16_t2字节记录压缩列表包含的节点数量,当这个值等于UINT16_MAX时,节点数量需要遍历整个压缩列表才能得出
entryX列表节点不定压缩列表的各个节点,长度由节点保存的内容决定
zlenduint8_t1字节特殊值0xFF,用于标记压缩列表末端

压缩列表节点的构成

压缩列表节点可以保存一个字节数组或一个整数值。

字节数组可以保存3种长度中的1种

  • 长度小于等于2^6 - 1字节
  • 长度小于等于2^14 - 1字节
  • 长度小于等于2^32 -1字节

整数值可以是6种长度中的一种

  • 4位长,0-12的无符号整数
  • 1字节长 有符号整数
  • 3字节长 有符号整数
  • int16_t
  • int32_t
  • int64_t

每个压缩节点由previous_entry_lengthencodingcontent三部分组成

previous_entry_length

以字节为单位,记录了压缩列表中前一个节点的长度
本身的长度可以是1字节或者5字节

  • 如果前一个节点长度小于254字节,那么该属性长度为1字节,前一字节的长度保存在这个字节里面
  • 如果前一个节点长度大于等于254字节,那么该属性长度为5字节。属性的第一字节会被设置为0xFE,之后的4个字节用来存储前一个节点的长度

通过previous_entry_length,可以很方便地通过节点自身的地址推算出前一个节点的地址

encoding

encoding记录了节点的content属性所保存数据的类型和长度

  • 1字节、2字节、5字节长,值最高位为00、01或者10的是字节数组编码,表示content保存着字节数组,数组的长度由编码除去最高两位之后的其他位记录
  • 1字节长,值最高位以11开头的是整数编码,表示保存了整数值,整数值的类型和长度由编码除去最高两位之后的其他位记录
    字节数组编码
    整数编码

content

content负责保存节点的值

连锁更新

产生的原因是previous_entry_length属性记录了前一个节点的长度。
假设e1 - eN 这N个节点的previous_entry_length都是一个字节长且本身长度在250-253字节之间,此时在e1前方插入一个长度不小于254字节的节点,此时e1的previous_entry_length就需要更新为5字节,此时e1又将不小于254字节,因此也需要更新e2…直到不需要更新为止,这就是连锁更新
删除节点也可能导致连锁更新

每次更新节点都将产生内存重分配,且最坏情况下连锁更新的复杂度为O(N^2)

但是连锁更新造成性能问题的几率很低:

  • 要有多个连续的且长度在250-253字节之间的节点才可能引发连锁更新,实际中这种情况并不常见
  • 连锁更新时,只要被更新的节点数不多,也不会对性能有所影响

压缩列表API

压缩列表API

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值