Redis的底层数据结构-List(IT枫斗者)
Redis3.0之前:ziplist/linkedlist
Redis3.0之后:quicklist
1、ziplist
1.1、什么是ziplist?
ziplist是一个经过特殊编码的双向链表,它的设计目标就是为了提高存储效率。
1.2、ziplist结构

zlbytes:ziplist的长度,32位无符号整数。
zltail:ziplist最后一个节点的偏移量,反向遍历ziplist或者pop尾部节点的时候用来提升性能。
zllen:ziplist的entry(节点)个数。
entry:节点,并不是一个数组,然后里面存的值,而是一个数据结构。下面说。
zlend:值为255,用于标记ziplist的结尾。


1.3、总结
ziplist是为节省内存空间而生的。
ziplist是一个为Redis专门提供的底层数据结构之一,本身可以有序也可以无序。当作为list和hash的底层实现时,节点之间没有顺序;当作为zset的底层实现时,节点之间会按照大小顺序排列。
ziplist的弊端也很明显了,对于较多的entry或者entry长度较大时,需要大量的连续内存,并且节省的空间比例相对不再占优势,就可以考虑使用其他结构了。
2、linkedlist
就是双向链表,对首尾节点的定位很快,O(1)复杂度。在首位前后插入节点也是O(1)。
3、ziplist和linkedlist怎么选择?
Redis的list类型什么时候会使用ziplist编码,什么时候又会使用linkedlist编码呢?
当列表对象可以同时满足下列两个条件时,列表对象采用ziplist编码,否则采用linkedlist编码。
列表对象保存的所有字符串元素的长度都小于64字节;
列表元素保存的元素数量小于512个;
上述两个参数可以更改配置进行自定义。
4、quicklist


5、总结
linkedlist:
双端链表便于在表的两端进行push和pop操作,但是它的内存开销比较大;
双端链表每个节点上除了要保存数据之外,还要额外保存两个指针(pre/next);
双端链表的各个节点是单独的内存块,地址不连续,节点多了容易产生内存碎片;
ziplist:
ziplist由于是一整块连续内存,所以存储效率很高;
ziplist不利于修改操作,每次数据变动都会引发一次内存的realloc;
当ziplist长度很长的时候,一次realloc可能会导致大批量的数据拷贝,进一步降低性能;
quicklist:
空间换时间,之前linkedlist需要两个指针,浪费空间,我现在不用linkedlist,我都采取ziplist,然后上面封装一层quicklistnode,底层存储还是ziplist,只是空间上多了一层指针用于检索。
结合了双端链表和压缩列表的优点。