Redis的Ziplist数据结构

压缩列表是是hash和list的底层实现。他的数据结构如下:
这里写图片描述

  • zlbytes:32bit,ziplist占用的总字节数
  • zltail:32bit,标记最后一个entry所在的位置(偏移字节数),这样无需遍历整个ziplist就可以快速的定位到最后一项,方便进行push或pop操作
  • zllen:16bit,entry的总数量。当entry的实际数量超过zllen所能保存的最大值2^16-1时,有如下约定:entry数量小于等于2^16-2,zllen保存entry数量值;entry数量大于2^16-2,zllen=2^16-1,通过遍历ziplist获取实际的entry个数
  • entry:真正存放数据的数据项,有自己的数据结构,长度不定
  • zlend:ziplist结束标记,1字节,值为255

entry的结构:
prevrawlen | len | data

  • prevrawlen:上一个数据项长度,变长编码。用于反向遍历时快速查找上一数据项
  • len:当前数据项长度,变长编码
  • data:存储的数据

那么,上面提到的变长编码是什么呢?它是指redis里对该字段的自定义的可变长度的编码约定,不同的字段有不同的约定方式。比如:

prevrawlen的编码方式
两种可能,或者是1个字节,或者是5个字节:
1. 如果前一个数据项占用字节数小于254,那么就只用一个字节来表示,这个字节的值就是前一个数据项的>占用字节数。
2. 如果前一个数据项占用字节数大于等于254,那么就用5个字节来表示,其中第1个字节的值是254(作为这种情况的一个标记),而后面4个字节组成一个整型值,来真正存储前一个数据项的占用字节数。

len的编码方式
len字段就更加复杂了,它根据第1个字节的不同,总共分为9种情况(下面的表示法是按二进制表示):
1. |00pppppp| - 1 byte。第1个字节最高两个bit是00,那么字段只有1个字节,剩余的6个bit用来表示长度值,最高可以表示63 (2^6-1)。
2. |01pppppp|qqqqqqqq| - 2 bytes。第1个字节最高两个bit是01,那么字段占2个字节,总共有14个bit用来表示长度值,最高可以表示16383 (2^14-1)。
3. |10__|qqqqqqqq|rrrrrrrr|ssssssss|tttttttt| - 5 bytes。第1个字节最高两个bit是10,那么len字段占5个字节,总共使用32个bit来表示长度值(6个bit舍弃不用),最高可以表示2^32-1。需要注意的是:在前三种情况下,都是按字符串来存储的;从下面第4种情况开始,开始变为按整数来存储了。
4. |11000000| - 1 byte。字段占用1个字节,值为0xC0,后面的数据存储为2个字节的int16_t类型。
5. |11010000| - 1 byte。字段占用1个字节,值为0xD0,后面的数据存储为4个字节的int32_t类型。
6. |11100000| - 1 byte。字段占用1个字节,值为0xE0,后面的数据存储为8个字节的int64_t类型。
7. |11110000| - 1 byte。字段占用1个字节,值为0xF0,后面的数据存储为3个字节长的整数。
8. |11111110| - 1 byte。字段占用1个字节,值为0xFE,后面的数据存储为1个字节的整数。
9. |1111xxxx| - - (xxxx的值在0001和1101之间)。这是一种特殊情况,xxxx从1到13一共13个值,这时就用这13个值来表示真正的数据。注意,这里是表示真正的数据,而不是数据长度了。也就是说,在这种情况下,后面不再需要一个单独的字段来表示真正的数据了,而是和合二为一了。另外,由于xxxx只能取0001和1101这13个值了(其它可能的值和其它情况冲突了,比如0000和1110分别同前面第7种第8种情况冲突,1111跟结束标记冲突),而小数值应该从0开始,因此这13个值分别表示0到12,即xxxx的值减去1才是它所要表示的那个整数数据的值。

以上便是ziplist在内存中的存储结构。至于为什么叫压缩列表,内存利用率是不是比一般的更高,暂时还没空研究。下次补充吧。

参考资料:
Redis之ziplist数据结构
Redis内部数据结构详解(4)——ziplist

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值