引用https://segmentfault.com/a/1190000016901154中的两个图:


6.1 源码
ziplist没有明确定义结构体,这里只作大概的演示。
- typedef struct entry {
- /*前一个元素长度需要空间和前一个元素长度*/
- unsigned int prevlengh;
- /*元素内容编码*/
- unsigned char encoding;
- /*元素实际内容*/
- unsigned char *data;
- }zlentry;
- typedef struct ziplist{
- /*ziplist分配的内存大小*/
- uint32_t zlbytes;
- /*达到尾部的偏移量*/
- uint32_t zltail;
- /*存储元素实体个数*/
- uint16_t zllen;
- /*存储内容实体元素*/
- unsigned char* entry[];
- /*尾部标识*/
- unsigned char zlend;
- }ziplist;
第一次看可能会特别蒙蔽,你细细的把我这段话看完就一定能懂。
Entry的分析
entry结构体里面有三个重要的字段:
- previous_entry_length: 这个字段记录了ziplist中前一个节点的长度,什么意思?就是说通过该属性可以进行指针运算达到表尾向表头遍历,这个字段还有一个大问题下面会讲。
- encoding:记录了数据类型(int16? string?)和长度。
- data/content: 记录数据。
连锁更新
previous_entry_length字段的分析
上面有说到,previous_entry_length这个字段存放上个节点的长度,那默认长度给分配多少呢?redis是这样分的,如果前节点长度小于254,就分配1字节,大于的话分配5字节,那问题就来了。
如果前一个节点的长度刚开始小于254字节,后来大于254,那不就存放不下了吗? 这就涉及到previous_entry_length的更新,但是改一个肯定不行阿,后面的节点内存信息都需要改。所以就需要重新分配内存,然后连锁更新包括该受影响节点后面的所有节点。
除了增加新节点会引发连锁更新、删除节点也会触发。
7. 快速列表(quicklist)
一个由ziplist组成的双向链表。但是一个quicklist可以有多个quicklist节点,它很像B树的存储方式。是在redis3.2版本中新加的数据结构,用在列表的底层实现。

结构体源码
表头结构:
- typedef struct quicklist {
- //指向头部(最左边)quicklist节点的指针
- quicklistNode *head;
- //指向尾部(最右边)quicklist节点的指针
- quicklistNode *tail;
- //ziplist中的entry节点计数器
- unsigned long count; /* total count of all entries in all ziplists */
- //quicklist的quicklistNode节点计数器
- unsigned int len; /* number of quicklistNodes */
- //保存ziplist的大小,配置文件设定,占16bits
- int fill : 16; /* fill factor for individual nodes */
- //保存压缩程度值,配置文件设定,占16bits,0表示不压缩
- unsigned int compress : 16; /* depth of end nodes not to compress;0=off */
- } quicklist;
(编辑:晋中站长网)
【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!
|