ziplist 是redis中常用数据的底层数据结构,包括列表键(list)、哈希键(hash)和有序集合(zset)。
typedef struct ziplist {
long zlbytes; //用于记录整个压缩列表占用的内存字节数
zskiplistNode *zltail; //记录要列表尾节点距离压缩列表的起始地址有多少字节
int zllen; //记录了压缩列表包含的节点数量
long entryX; //要说列表包含的各个节点
long zlend; //用于标记压缩列表的末端
}
1. ziplist的特性
ziplist是一个经过特殊编码的双向链表,内存地址空间是连续的,更像是一个list,只是比list多了一个链表的首尾操作而已。它的设计目标就是为了提高存储效率。
因为空间的连续,所以缺点也比较鲜明。
第一点:降低了查询速度(连续的空间,所以查询元素需要进行遍历O(n))
第二点:提高了插入的复杂度及成本(每次插入或修改引发的重新分配内存(realloc)操作会有更大的概率造成内存拷贝,从而降低性能。跟list一样,一旦发生内存拷贝,内存拷贝的成本也相应增加,因为要拷贝更大的一块数据。)
2. ziplist的应用
一开始,我们提到 ziplist 可以作为list、hash与zset的底层数据结构,但是这都是有条件的,这部分也是作者在设计时考虑并优化才这么做的。
list:当一个列表键只包含少量列表项, 并且每个列表项要么就是小整数值, 要么就是长度比较短的字符串, 那么就会使用压缩列表来做列表键的底层实现。
hash:在field比较少,各个value值也比较小的时候,hash采用ziplist来实现。注:而随着field增多和value值增大,hash可能会变成dict来实现。
zset:数据符合一下两点才会由zipList实现,反之是由skipList和hashTable实现的。
-
[score,value]
键值对数量少于128个; -
每个元素的长度小于64字节;