Redis ziplist(压缩列表)(6)
目录:1.什么是ziplist2.散列表和ziplist3.有序集合和ziplistRedis 为了节约内存空间使用,zset 和 hash 容器对象在元素个数较少的时候,采用压缩列表 (ziplist) 进行存储。什么是ziplist?ziplist是一块连续的内存空间,元素之间紧挨着存储,没有任何冗余空隙。它的设计目标就是为了提高存储效率。ziplist可以用于存储字符...
目录:
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;
}
如图:
各部分的含义如下:
- zlbytes:整个压缩列表占用字节数,包含本身
- zltail_offset:最后一个元素距离压缩列表起始位置的偏移量,用于快速定位到最后一个节点,从而可以在ziplist尾部快速的执行push,pop操作
- zllength:元素个数,该字段只有16bit所以可以表达的最大值为2^16-1,如果ziplist元素超了该值呢?这里规定,如果zllength小于等于 2^16-2,该字段表示为ziplist中元素的个数,否则想知道ziplist长度需要遍历整个ziplist
- entries:元素内容列表,挨个挨个紧凑存储
- 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内部实现
hash与ziplist
在以前的文章里,没有对hash结构做出分析,这里我们简单的说下hash的实现
哈希对象的编码可以是ziplist或者dict,数据量比较少的时候hash底层是用ziplist来实现的,那么什么条件下会转换成dict 呢?
hash-max-ziplist-entries 512
hash-max-ziplist-value 64
这个配置的意思是说,在如下两个条件之一满足的时候,ziplist会转成dict:
- 当hash中的数据项的数目超过512的时候,也就是ziplist数据项超过1024的时候(后文会讲为什么是1024个)。
- 当hash中插入的任意一个value的长度超过了64的时候
这里我说说ziplist是怎么保存hash结构的,dict还不熟悉的同学可以翻翻之前写的那篇字典 redis 字典详解
每当有新的键值对加入到哈希对象时,程序会先将保存了键的压缩列表节点推入到压缩列表表尾,然后在将保存了值的压缩列表节点推入到压缩列表表尾,因此:
- 保存了同一键值对的两个节点总是紧挨在一起,保存键的节点在前,保存值的节点在后(所以是当ziplist节点超过1024个以后会转换成dict)
- 新添加的节点总是放入表尾
见图:
当遍历时,从头到尾的遍历,且跳过值节点。
有序集合 和 ziplist
有序集合底层是用ziplist和跳表实现的(跳表详情实现见:redis 有序集合内部实现)
zset-max-ziplist-entries 128
zset-max-ziplist-value 64
有序集合的ziplist结构如图:
有序集合的分值在ziplist里按照从小到大排序的
更多推荐
所有评论(0)