Redis数据结构之ZipList

Redis数据结构之ZipList

什么是ZipList

ZipList 也叫压缩链表,可以被看作是一种连续空间的 “双端链表”

但它并不是链表,它并不存储指针,通过字节长度和偏移量之间的计算来寻址,查找时间复杂度为O(n)。所以:它是一种以时间换空间的数据结构。

首尾的操作复杂度为O(1);

但是压缩列表通过申请连续的内存空间存储,节省空间,这是它优点,同时也是它缺点,因为当数据量越来越大时,并不能保证能申请到大的连续的内存空间,查询性能也会下降(O(n)),所以一般当数据量达到一定程度时,需要转成其他存储结构。比如quicklist、hash等。

ZipList 结构

ZipList 头部由三个固定长度的属性(zlbytes、zltail、zllen)(长度分别是4字节、4字节、2字节)组成;
尾部由1个字节长度的 zlend (内容是16进制的0xff ) , 标记尾部;
中间就是存储了数据部分的节点entry,长度不固定,由存储的内容决定;

结构大致长这样:

zlbyteszltailzllenentryentryzlend
4字节4字节2字节不确定不确定1字节

ZipList各属性的含义

属性长度含义
zlbytes4字节整个压缩链表占用的内存字节数
zltail4字节压缩列表表尾节点距离压缩列表的起始地址的字节数(最后一个entry的起始地址压缩列表起始地址的字节数),即偏移量
zllen2字节压缩列表包含的节点数量。最大为 UINT16_MAX (65534),如果超出,仍只能记录为65535,但真实数量需要遍历整个压缩列表
entry不确定保存内容的节点,长度与保存的内容有关
zlend1字节保存了16进制的 (0xff) 也就是十进制的 255,标记列表末端

列表节点entry

压缩列表并没有存储指针,那么压缩列表各个节点之间是如何做到两端都能访问的呢?

这就是每个列表节点entry的结构厉害之处,每个entry保存了三个属性,分别是:

  • previous_entry_length(前一个节点的长度)
    • 如果前一个节点长度小于254 (<254),则用1个字节保存这个长度
    • 如果前一个节点长度大于等于254 (>=254),则采用5个字节长度保存,其中第一个字节为0xfe,后面四个节点才是真实的数据长度;
  • encoding(编码)
    • 记录content内容的 数据类型 以及 长度,占1、2或5个字节长度
    • 以’00’, ‘01’, ‘10’ 开头,那么content保存的是字符串
    • 以 ‘11’ 开头则保存的是整数
  • contents(保存的内容)
    • 保存数据的地方,可以是字符串或者整数。
属性previous_entry_lengthencodingcontents
含义前一个节点长度content的数据类型以及长度数据内容
大小1 或 5 个字节1 或 2 或 5个字节encoding中存储

因为254是zlend保存的,所以previous_entry_length在>=254时就要用另一张方法区别

从前往后:压缩列表起始地址+10个字节,就是第一个entry的起始地址;
从后往前:压缩列表起始地址+zltail,就是最后一个entry的起始地址;

连锁更新

连锁更新发生的概率较低,在新增或者删除的时候会发生;

发生的原因是entry中的previous_entry_length存储机制;

previous_entry_length中存储的是前一个节点的长度,当前一个节点长度 <254 时 previous_entry_length只占一个字节,>= 254 时占5个字节;

假设现在有连续 n 个列表节点entry,并且每个entry长度都在 250 ~ 253之间(包括);

此时向这最前面的 entry1 前插入一个 >= 254长度节点,那么 entry1 节点的previous_entry_length就要变成5字节长度,entry1 节点长度+4 >= 254了,所以下一节点entry2的previous_entry_length也要变成5个字节长度entry2长度也+4 ,又 >= 254了,所以entry3的previous_entry_length…

这种连续的空间扩张,被称为连锁更新,发生的概率非常低,但是由于要不断地去申请空间,和释放内存,所以会严重影响性能;

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值