redis的几个数据结构——ziplist

背景

ziplist是列表、hash和zset元素较少时的存储格式:

  1. hash:
    • 当哈希类型元素个数小于hash-max-ziplist-entries配置(默认512个);
    • 所有值小于hash-max-ziplist-value配置(默认64个字节);
  2. sorted set:
    • 元素个数小于zset-max-ziplist-entries配置,默认128;
    • 所有值小于zset-max-ziplist-value配置,默认64。

实现

如下图所示,zlist由下面几个元素组成:

  • zlbytes :字节长度,4个字节
  • zltail:尾部偏移量
  • zllen :元素个数
  • entryX :元素
  • zlend :结尾字符

redisxiancheng8

ziplist中所有元素都是紧凑的排在一起的,我们来看一下每个元素的组成:

  • previous_entry_length:前一个元素的字节长度,方便从尾部遍历。
  • encoding:当前元素编码
  • content:数据内容

redisxiancheng9

其中encoding的取值:根据encoding字段第1个字节的前2位,可以判断content字段存储的是整数或者字节数组。当content存储的是字节数组时,后续字节标识字节数组的实际长度;当content存储的是整数时,可根据第3、第4位判断整数的具体类型。而当encoding字段标识当前元素存储的是0~12的立即数时,数据直接存储在encoding字段的最后4位,此时没有content字段。
redisxiancheng11

redis通过每一项放在前后连续的内存中,以使提高存储效率,但是这样也会导致级联更新的问题。当插入的数据的位置前后都有数据的时候,需要调整插入位置后面的元素,把后面的元素全部往后挪,并修改后面一个元素的previous_entry_length,后面的元素可能增加4个字节、减少4个字节或不变。就是因为previous_entry_length占用的字节和上一个元素的大小有关,所以如果刚好后面的元素都处于临界点,那么就有可能引起级联更新,当然出现这种情况的概率比较小。

redis级联更新的情况:
redis----

comments powered by Disqus