目录:

1.什么是ziplist

2.散列表和ziplist

3.有序集合和ziplist


Redis 为了节约内存空间使用,zset 和 hash 容器对象在元素个数较少的时候,采用压缩列表 (ziplist) 进行存储。

什么是ziplist?

ziplist是一块连续的内存空间,元素之间紧挨着存储,没有任何冗余空隙。它的设计目标就是为了提高存储效率。ziplist可以用于存储字符串或整数,其中整数是按真正的二进制表示进行编码的,而不是编码成字符串序列。它能以O(1)的时间复杂度在表的两端提供push和pop操作。

ziplist的数据结构定义:

struct ziplist<T> {
  int32 zlbytes;   
  int32 zltail_offset; 
  int16 zllength; 
 T[] entries; 
 int8 zlend; 
}

如图:

各部分的含义如下:

  1. zlbytes:整个压缩列表占用字节数,包含本身
  2.  zltail_offset:最后一个元素距离压缩列表起始位置的偏移量,用于快速定位到最后一个节点,从而可以在ziplist尾部快速的执行push,pop操作
  3. zllength:元素个数,该字段只有16bit所以可以表达的最大值为2^16-1,如果ziplist元素超了该值呢?这里规定,如果zllength小于等于   2^16-2,该字段表示为ziplist中元素的个数,否则想知道ziplist长度需要遍历整个ziplist
  4.  entries:元素内容列表,挨个挨个紧凑存储
  5. zlend:ziplist最后一个字节,标志压缩列表的结束,值恒为 0xFF(255)

压缩列表为了支持双向遍历,所以才会有 ztail_offset 这个字段,用来快速定位到最后一个元素,然后倒着遍历。我们知道ziplist是一块连续的内存,entry的大小不确定,我们倒着遍历ziplist怎么能找到上个一个节点的开始位置呢?

entry 块随着容纳的元素类型不同,也会有不一样的结构。

struct entry {
    int<var> prevlen; # 前一个 entry 的字节长度
    int<var> encoding; # 元素类型编码
    optional byte[] content; # 元素内容
}

它的 prevlen 字段表示前一个 entry 的字节长度,当压缩列表倒着遍历时,需要通过这个字段来快速定位到下一个元素的位置。它是一个变长的整数,当字符串长度小于 254(0xFE) 时,使用一个字节表示;如果达到或超出 254(0xFE) 那就使用 5 个字节来表示。

Redis 为了节约存储空间,对 encoding 字段进行了相当复杂的设计,他根据第一个字节的不同大概分为9种情况。这里就不做过多的介绍了,有兴趣的同学可以看看张铁磊这篇  redis ziplist内部实现


hashziplist

在以前的文章里,没有对hash结构做出分析,这里我们简单的说下hash的实现

哈希对象的编码可以是ziplist或者dict,数据量比较少的时候hash底层是用ziplist来实现的,那么什么条件下会转换成dict 呢?

hash-max-ziplist-entries 512
hash-max-ziplist-value 64

这个配置的意思是说,在如下两个条件之一满足的时候,ziplist会转成dict:

  1. 当hash中的数据项的数目超过512的时候,也就是ziplist数据项超过1024的时候(后文会讲为什么是1024个)。
  2. 当hash中插入的任意一个value的长度超过了64的时候

这里我说说ziplist是怎么保存hash结构的,dict还不熟悉的同学可以翻翻之前写的那篇字典 redis 字典详解

每当有新的键值对加入到哈希对象时,程序会先将保存了键的压缩列表节点推入到压缩列表表尾,然后在将保存了值的压缩列表节点推入到压缩列表表尾,因此:

  1. 保存了同一键值对的两个节点总是紧挨在一起,保存键的节点在前,保存值的节点在后(所以是当ziplist节点超过1024个以后会转换成dict)
  2. 新添加的节点总是放入表尾

见图:

当遍历时,从头到尾的遍历,且跳过值节点。


有序集合 ziplist

有序集合底层是用ziplist和跳表实现的(跳表详情实现见:redis 有序集合内部实现

zset-max-ziplist-entries 128
zset-max-ziplist-value 64

有序集合的ziplist结构如图:

有序集合的分值在ziplist里按照从小到大排序的

Logo

权威|前沿|技术|干货|国内首个API全生命周期开发者社区

更多推荐