Redis 数据结构之【压缩列表】

含义:

压缩列表是一块连续的内存空间,元素之间紧挨着存储,没有任何冗余空隙。

内部结构 : 

  struct ziplist<T> {
     int32 zlbytes; // 整个压缩列表占用字节数
     int32 zltail_offset; // 最后一个元素距离压缩列表起始位置的偏移量,用于快速定位到最后一个节点
     int16 zllength; // 元素个数
     T[] entries; // 元素内容列表,挨个挨个紧凑存储
     int8 zlend; // 标志压缩列表的结束,值恒为 0xFF
  } 
  entry 块随着容纳的元素类型不同,也会有不一样的结构。
  struct entry {
      int<var> prevlen; // 前一个 entry 的字节长度
      int<var> encoding; // 元素类型编码
      optional byte[] content; // 元素内容
  } 

       encoding 字段存储了元素内容的编码类型信息,ziplist 通过这个字段来决定后面的 content 内容的形式。 Redis 为了节约存储空间,对 encoding 字段进行了相当复杂的设计。Redis 通过这个字段的前缀位来识别具体存储的数据形式。下面我们来看看 Redis 是如何根据 encoding 的前缀位来区分内容的:  

  •     1、00xxxxxx 最大长度位 63 的短字符串,后面的 6 个位存储字符串的位数,剩余的字节就是字符串的内容。 
  •     2、01xxxxxx xxxxxxxx 中等长度的字符串,后面 14 个位来表示字符串的长度,剩余的字节就是字符串的内容。 
  •     3、10000000 aaaaaaaa bbbbbbbb cccccccc dddddddd 特大字符串,需要使用额外 4 个字节来表示长度。第一个字节前缀是 10,剩余 6 位没有使用,统一置为零。后面跟着字符串内容。不过这样的大字符串是没有机会使用的,压缩列表通常只是用来存储小数据的。 
  •     4、11000000 表示 int16,后跟两个字节表示整数。 
  •     5、11010000 表示 int32,后跟四个字节表示整数。 
  •     6、11100000 表示 int64,后跟八个字节表示整数。 
  •     7、11110000 表示 int24,后跟三个字节表示整数。 
  •     8、11111110 表示 int8,后跟一个字节表示整数。 
  •     9、11111111 表示 ziplist 的结束,也就是 zlend 的值 0xFF。 
  •     10、1111xxxx 表示极小整数,xxxx 的范围只能是 (0001~1101), 也就是 1~13,因为0000、1110、1111 都被占用了。读取到的 value 需要将 xxxx 减 1,也就是整数 0~12 就是最终的 value。 

使用: 

  • 最早期的 list 采用链表加压缩列表
  •  zset 元素个数较少的时候;
  • hash 元素个数较少的时候;

 增加元素 :

        因为 ziplist 都是紧凑存储,没有冗余空间 (对比一下 Redis 的字符串结构)。意味着插入一个新的元素就需要调用 realloc 扩展内存。取决于内存分配器算法和当前的 ziplist 内存大小,realloc 可能会重新分配新的内存空间,并将之前的内容一次性拷贝到新的地址,也可能在原有的地址上进行扩展,这时就不需要进行旧内容的内存拷贝。 如果 ziplist 占据内存太大,重新分配内存和拷贝内存就会有很大的消耗。所以 ziplist 不适合存储大型字符串,存储的元素也不宜过多。 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值