首页 > 编程知识 正文

redis数据结构详解,redis zset数据结构

时间:2023-05-03 14:22:07 阅读:31302 作者:1323

回顾一下在上一个博客的Redis数据结构的intset中,我们了解了Redis的intset (整数集合),今天我们来了解一下Redis的快速列表。

版本3.2在版本3.2的Redis中进行了分析,以前版本的Redis中没有此结构。

源地址: redis/quicklist.h和redis/quicklist.c。

概要在Redis/quicklist.c中说A doubly linked list of ziplists,翻译过来是“quicklist是ziplist的双向链表”(redis数据结构ziplist )。

结构与源地址相对应。 redis /快速列表. h。

快速列表快速列表主结构

typedef struct quicklist {//头节点quicklistNode *head; //结尾节点快速列表* tail; //所有ziplist的节点数(可以理解为数据项)无符号长计数;/* totalcountofallentriesinallziplists *///quick list节点的数量未指定的int len;/*快速列表编号*///单个zip列表的大小设置、“list-max-ziplist-size”值、16位int文件: 16;/* fillfactorforindividualnodes *//节点压缩程度的值,0为未压缩," list-compress-depth "的值、16位无符号int compress 3360 16; /* depth of end nodes not to compress; 0=off */}快速列表; 快速列表快速列表结构中的节点

typedef struct quicklistNode {//指向上一个节点的指针struct quicklistNode *prev; //指向下一个节点的指针“结构快速列表*下一个”; 指向zip列表的指针unsigned char *zl; //指示的ziplist的总大小unsigned int sz;/* ziplistsizeinbytes *///zip list中包含的数据项数unsigned int count : 16;/*在items中的计数*//指示zip列表是否已压缩。 用2-lzf算法压缩、1本机未压缩的无符号内编码: 2; /* RAW==1 or LZF==2 *///字段保留,数据存储方式,1--NONE,2---- ziplistunsignedintcontainer 3360; 当您看到使用类似/* none==1orz iplist==2*///lindex的命令的原始压缩数据时,必须临时解压缩数据。 此时,标记recompress=1,有机会时重新压缩数据。 未指定int re compress : 1;/* wasthisnodepreviouscompressed? //unsignedintattempted _ compress :1;/*节点can ' t compress; too small *///扩展字段unsigned int extra : 10;/* morebitstostealforfutureusage */}快速列表节点; quicklistLZF此结构表示压缩的ziplist

/* quicklistlzfisa4nbytestructholding ' SZ ' followed by ' compressed '.* ' SZ ' isbytelengthof ' compresssed ' field.* ' compressed ' islzfdatawithtotal (compressed ) length ' SZ ' * note : uncompressedlengthisstoredinquicklistnode-SZ.* www node-zlpointstoaquicklistlzf */typedefstructquicklistlzf {///压缩的zip列表

大小 unsigned int sz; /* LZF size in bytes*/ // 存放被压缩后的 ziplist 字节数组 char compressed[];} quicklistLZF; 整理

通过上面三段代码的解释,大概知道了 quicklist 的结构,大概就是下图所示:

备注

参考:从ziplist到quicklist,再到listpack的启发

quicklist 并没有解决 ziplist 中的「连锁更新」问题,只是减少了在 压缩链表 ziplist 中新增或修改元素发生连锁更新的情况。

过程如下:

当插入一个新的元素时,quicklist 首先就会检查插入位置的 ziplist 是否能容纳该元素,这是通过 _quicklistNodeAllowInsert 函数来完成判断的。

_quicklistNodeAllowInsert 函数会计算新插入元素后的大小(new_sz),这个大小等于 quicklistNode 的当前大小(node->sz)、插入元素的大小(sz),以及插入元素后 ziplist 的 prevlen 占用大小。

计算完大小之后,_quicklistNodeAllowInsert 函数会依次判断新插入的数据大小(sz)是否满足要求,即单个 ziplist 是否不超过 8KB,或是单个 ziplist 里的元素个数是否满足要求。

只要这里面的一个条件能满足,quicklist 就可以在当前的 quicklistNode 中插入新元素,否则 quicklist 就会新建一个 quicklistNode,以此来保存新插入的元素。

unsigned int new_sz = node->sz + sz + ziplist_overhead;if (likely(_quicklistNodeSizeMeetsOptimizationRequirement(new_sz, fill))) return 1;else if (!sizeMeetsSafetyLimit(new_sz)) return 0;else if ((int)node->count < fill) return 1;else return 0;

quicklist 通过控制每个 quicklistNode 中,ziplist 的大小或是元素个数,就有效减少了在 ziplist 中新增或修改元素后,发生连锁更新的情况,从而提供了更好的访问性能。

分析

在 Redis 3.2 之前,在选用了 list 的情况下:

元素较少的情况下,比较适合用 ziplist,毕竟创建双向链表浪费空间,而且此时元素较少,修改 ziplist 中的元素的效率也不会低到哪里去;元素较多的情况下,比较适合用 adlist(linkedlist),元素较多,修改的效率也不会太低。

有了 quicklist,算是在 ziplist 和 adlist(linkedlist) 之间有了折衷的方案。

还可以通过 list-max-ziplist-size 配置:

当取正值的时候,表示按照数据项个数来限定每个 quicklist 节点上的 ziplist 长度。比如,当这个参数配置成5的时候,表示每个 quicklist 节点的 ziplist 最多包含 5 个数据项。当取负值的时候,表示按照占用字节数来限定每个 quicklist 节点上的 ziplist 长度。这时,它只能取 -1 到 -5 这五个值,每个值含义如下:
-5: 每个 quicklist 节点上的 ziplist 大小不能超过 64Kb。(注:1kb => 1024 bytes)
-4: 每个 quicklist 节点上的 ziplist 大小不能超过 32Kb。
-3: 每个 quicklist 节点上的 ziplist 大小不能超过 16Kb。
-2: 每个 quicklist 节点上的 ziplist 大小不能超过 8Kb。(-2 是 Redis 给出的默认值)
-1: 每个 quicklist 节点上的 ziplist 大小不能超过 4 Kb。 关联阅读

Redis 基础

Redis 数据结构 SDS

Redis 数据结构 linkedlist

Redis 数据结构 hashtable

Redis 数据结构 skiplist

Redis 数据结构 ziplist

Redis 数据结构 intset

Redis 数据结构 quicklist

Redis 对象 RedisObject

版权声明:该文观点仅代表作者本人。处理文章:请发送邮件至 三1五14八八95#扣扣.com 举报,一经查实,本站将立刻删除。