关于list:Redis数据结构二ListHashSet及Sorted-Set的结构实现
1 引言之前介绍了Redis的数据存储及String类型的实现,接下来再来看下List、Hash、Set及Sorted Set的数据结构的实现。 2 ListList类型通常被用作异步音讯队列、文章列表查问等;存储有序可反复数据或做为简略的音讯推送机制时,能够应用Redis的List类型。对于这些数据的存储通常会应用链表或者数组作为存储构造。 应用数组存储,随机拜访节点通过索引定位工夫复杂度为O(1)。但在初始化时须要调配间断的内存空间;在减少数据时,如果超过以后调配空间,须要将数据整体搬迁徙到新数组中。应用链表存储,在进行前序遍历或后续遍历,以后节点中要存储前指针和后指针,这两个指针在别离须要8byte共16byte空间存储,存在大量节点会因指针占用过多空间。链表尽管不须要间断空间存储能够进步内存利用率,但频繁的减少和删除操作会使内存碎片化,影响数据读写速率。如果咱们可能将链表和数组的特点联合起来就可能很好解决List类型的数据存储。 2.1 ZipList3.2之前Redis应用的是ZipList,具体构造如下: zlbytes: 4byte 记录整个压缩列表占用的内存字节数:在对压缩列表进行内存重调配, 或者计算 zlend 的地位时应用。zltail:4byte 记录压缩列表表尾节点间隔压缩列表的起始地址有多少字节: 通过这个偏移量,程序毋庸遍历整个压缩列表就能够确定表尾节点的地址。zllen:2byte 记录了压缩列表蕴含的节点数量: 当这个属性的值小于 UINT16\_MAX(65535)时, 这个属性的值就是压缩列表蕴含节点的数量; 当这个值等于UINT16\_MAX 时,节点的实在数量须要遍历整个压缩列表能力计算得出。entry X:压缩列表蕴含的各个节点,节点的长度由节点保留的内容决定。蕴含属性如下:prerawlen:记录前一个节点所占内存的字节数,不便查找上一个元素地址len:data依据len的首个byte选用不同的数据类型来存储datadata:本元素的信息zlend: 尾节点 恒等于255ziplist是一个间断的内存块,由表头、若干个entry节点和压缩列表尾部标识符zlend组成,通过一系列编码规定,进步内存的利用率,应用于存储整数和短字符串。每次减少和删除数据时,所有数据都在同一个ziplist中都会进行搬移操作。如果将一个组数据按阈值进行拆分出多个数据,就能保障每次只操作某一个ziplist。3.2之后应用的quicklist与ziplist。 2.2 QuickListquicklist就是保护了一种宏观上的双端链表(相似于B树),链表的节点为对ziplist包装的quicklistNode,每个quciklistNode都会通过前后指针互相指向,quicklist蕴含头、尾quicklistNode的指针。 typedef struct quicklist {quicklistNode *head;quicklistNode *tail;unsigned long count; /* total count of all entries in all ziplists */unsigned long len; /* number of quicklistNodes */int fill : QL_FILL_BITS; /* fill factor for individual nodes */unsigned int compress : QL_COMP_BITS; /* depth of end nodes not to compress;0=off */...} quicklist;*head:表头节点*tail:表尾节点count:节点蕴含entries数量len:quicklistNode节点计数器fill:保留ziplist的大小,配置文件设定compress:保留压缩水平值,配置文件设定quicklistNode: ...