首页 > 试题广场 >

说一说zset类型的底层数据结构

[问答题]

说一说zset类型的底层数据结构

推荐

得分点

​ ziplist、skiplist

参考答案

标准回答

 zset底层的存储结构包括ziplist或skiplist,在同时满足有序集合保存的元素数量小于128个和有序集合保存的所有元素的长度小于64字节的时候使用ziplist,其他时候使用skiplist。

 当ziplist作为zset的底层存储结构时候,每个集合元素使用两个紧挨在一起的压缩列表节点来保存,第一个节点保存元素的成员,第二个元素保存元素的分值。

 当skiplist作为zset的底层存储结构的时候,使用skiplist按序保存元素及分值,使用dict来保存元素和分值的映射关系。

加分回答

​ 压缩列表是Redis为了节约内存而开发的,它是由一系列特殊编码的连续内存块组成的顺序型数据结构。一个压缩列表可以包含多个节点,每个节点可以保存一个字节数组或者一个整数值。一个压缩列表的重要组成部分包括zlbytes、zltail、zllen、entryX、zlend,其类型长度以及用途如下表所示:

属性 类型 长度 说明
zlbytes uint32_t 4字节 压缩列表占用的内存字节数;
zltail uint32_t 4字节 压缩列表表尾节点距离列表起始地址的偏移量(单位字节);
zllen uint16_t 2字节 压缩列表包含的节点数量,等于UINT16_MAX时,需遍历列表计算真实数量;
entryX 列表节点 不固定 压缩列表包含的节点,节点的长度由节点所保存的内容决定;
zlend uint8_t 1字节 压缩列表的结尾标识,是一个固定值0xFF;

​ 跳跃表的查找复杂度为平均O(logN),最坏O(N),效率堪比红黑树,却远比红黑树实现简单。跳跃表是在链表的基础上,通过增加索引来提高查找效率的。

​ 有序链表插入、删除的复杂度为O(1),而查找的复杂度为O(N)。跳跃表从有序链表中选取部分节点,组成一个新链表,并以此作为原始链表的一级索引。再从一级索引中选取部分节点,组成一个新链表,并以此作为原始链表的二级索引。以此类推,可以有多级索引。跳跃表的实现主要涉及2个结构体:zskiplist、zskiplistNode。zskiplist有指向头尾节点的指针,以及列表的长度,列表中最高的层级。zskiplistNode的头节点是空的,它不存储任何真实的数据,它拥有最高的层级,但这个层级不记录在zskiplist之内。

延伸阅读

​ 有序链表插入、删除的复杂度为O(1),而查找的复杂度为O(N)。例:若要查找值为60的元素,需要从第1个元素依次向后比较,共需比较6次才行,如下图:


图片说明
​ 跳跃表是从有序链表中选取部分节点,组成一个新链表,并以此作为原始链表的一级索引。再从一级索引中选取部分节点,组成一个新链表,并以此作为原始链表的二级索引。以此类推,可以有多级索引,如下图:


图片说明
​ 跳跃表在查找时,优先从高层开始查找,若next节点值大于目标值,或next指针指向NULL,则从当前节点下降一层继续向后查找,这样便可以提高查找的效率了。

跳跃表的实现主要涉及2个结构体:zskiplist、zskiplistNode,它们的关系如下图所示:


图片说明
​ 其中,蓝色的表格代表zskiplist,红色的表格代表zskiplistNode。zskiplist有指向头尾节点的指针,以及列表的长度,列表中最高的层级。zskiplistNode的头节点是空的,它不存储任何真实的数据,它拥有最高的层级,但这个层级不记录在zskiplist之内。

编辑于 2021-09-15 10:55:59 回复(0)
这谁顶得住啊
发表于 2022-10-12 23:18:29 回复(0)

ziplist、skiplist

参考答案

标准回答

zset底层的存储结构包括ziplist或skiplist,在同时满足有序集合保存的元素数量小于128个和有序集合保存的所有元素的长度小于64字节的时候使用ziplist,其他时候使用skiplist。

当ziplist作为zset的底层存储结构时候,每个集合元素使用两个紧挨在一起的压缩列表节点来保存,第一个节点保存元素的成员,第二个元素保存元素的分值。

当skiplist作为zset的底层存储结构的时候,使用skiplist按序保存元素及分值,使用dict来保存元素和分值的映射关系。

加分回答

压缩列表是Redis为了节约内存而开发的,它是由一系列特殊编码的连续内存块组成的顺序型数据结构。一个压缩列表可以包含多个节点,每个节点可以保存一个字节数组或者一个整数值。一个压缩列表的重要组成部分包括zlbytes、zltail、zllen、entryX、zlend,其类型长度以及用途如下表所示:

属性 类型 长度 说明
zlbytes uint32_t 4字节 压缩列表占用的内存字节数;
zltail uint32_t 4字节 压缩列表表尾节点距离列表起始地址的偏移量(单位字节);
zllen uint16_t 2字节 压缩列表包含的节点数量,等于UINT16_MAX时,需遍历列表计算真实数量;
entryX 列表节点 不固定 压缩列表包含的节点,节点的长度由节点所保存的内容决定;
zlend uint8_t 1字节 压缩列表的结尾标识,是一个固定值0xFF;

跳跃表的查找复杂度为平均O(logN),最坏O(N),效率堪比红黑树,却远比红黑树实现简单。跳跃表是在链表的基础上,通过增加索引来提高查找效率的。

有序链表插入、删除的复杂度为O(1),而查找的复杂度为O(N)。跳跃表从有序链表中选取部分节点,组成一个新链表,并以此作为原始链表的一级索引。再从一级索引中选取部分节点,组成一个新链表,并以此作为原始链表的二级索引。以此类推,可以有多级索引。跳跃表的实现主要涉及2个结构体:zskiplist、zskiplistNode。zskiplist有指向头尾节点的指针,以及列表的长度,列表中最高的层级。zskiplistNode的头节点是空的,它不存储任何真实的数据,它拥有最高的层级,但这个层级不记录在zskiplist之内

发表于 2022-01-11 11:10:14 回复(0)
自己还是太菜了。。
发表于 2024-11-14 15:01:31 回复(0)
都卷的要把全世界的代码都背下来才能去扛砖头么
发表于 2023-02-04 13:25:26 回复(0)