数据结构论坛

首页 » 分类 » 分类 » Redis数据结构二ListHa
TUhjnbcbe - 2025/4/13 16:55:00

1引言

之前介绍了Redis的数据存储及String类型的实现,接下来再来看下List、Hash、Set及SortedSet的数据结构的实现。

2List

List类型通常被用作异步消息队列、文章列表查询等;存储有序可重复数据或做为简单的消息推送机制时,可以使用Redis的List类型。对于这些数据的存储通常会使用链表或者数组作为存储结构。

使用数组存储,随机访问节点通过索引定位时间复杂度为O(1)。但在初始化时需要分配连续的内存空间;在增加数据时,如果超过当前分配空间,需要将数据整体搬迁移到新数组中。

使用链表存储,在进行前序遍历或后续遍历,当前节点中要存储前指针和后指针,这两个指针在分别需要8byte共16byte空间存储,存在大量节点会因指针占用过多空间。链表虽然不需要连续空间存储可以提高内存利用率,但频繁的增加和删除操作会使内存碎片化,影响数据读写速率。

如果我们能够将链表和数组的特点结合起来就能够很好处理List类型的数据存储。

2.1ZipList

3.2之前Redis使用的是ZipList,具体结构如下:

zlbytes:4byte记录整个压缩列表占用的内存字节数:在对压缩列表进行内存重分配,或者计算zlend的位置时使用。

zltail:4byte记录压缩列表表尾节点距离压缩列表的起始地址有多少字节:通过这个偏移量,程序无须遍历整个压缩列表就可以确定表尾节点的地址。

zllen:2byte记录了压缩列表包含的节点数量:当这个属性的值小于UINT16_MAX()时,这个属性的值就是压缩列表包含节点的数量;当这个值等于UINT16_MAX时,节点的真实数量需要遍历整个压缩列表才能计算得出。

entryX:压缩列表包含的各个节点,节点的长度由节点保存的内容决定。包含属性如下:

prerawlen:记录前一个节点所占内存的字节数,方便查找上一个元素地址

len:data根据len的首个byte选用不同的数据类型来存储data

data:本元素的信息

zlend:尾节点恒等于

ziplist是一个连续的内存块,由表头、若干个entry节点和压缩列表尾部标识符zlend组成,通过一系列编码规则,提高内存的利用率,使用于存储整数和短字符串。每次增加和删除数据时,所有数据都在同一个ziplist中都会进行搬移操作。如果将一个组数据按阈值进行拆分出多个数据,就能保证每次只操作某一个ziplist。3.2之后使用的quicklist与ziplist。

2.2QuickList

quicklist就是维护了一种宏观上的双端链表(类似于B树),链表的节点为对ziplist包装的quicklistNode,每个quciklistNode都会通过前后指针相互指向,quicklist包含头、尾quicklistNode的指针。

typedefstructquicklist{quicklistNode*head;quicklistNode*tail;unsignedlongcount;/*totalcountofallentriesinallziplists*/unsignedlonglen;/*numberofquicklistNodes*/intfill:QL_FILL_BITS;/*fillfactorforindividualnodes*/unsignedint

1
查看完整版本: Redis数据结构二ListHa