存储原理
Redis3.2之前,列表对象其底层存储结构可以有两种,即:linkedlist和ziplist,而在Redis 3.2之后,列表对象底层存储结构优化成为了另一种:quicklist。而quicklist可以认为是linkedlist和ziplist的结合体。
当列表对象同时满足以下两个条件时,列表对象使用ziplist进行存储,否则用linkedlist存储。
- 列表对象保存的所有字符串元素的长度小于64字节
- 列表对象保存的元素数量小于512个。
linkedlist
linkedlist
是一个双向列表,每个节点都会存储指向上一个节点和指向下一个节点的指针。linkedlist
因为每个节点的空间是不连续的,所以可能会造成过多的空间碎片
ziplist
ziplist是为了节省内存而开发的一种压缩列表数据结构,后面讲述的哈希数据类型底层也用到了ziplist。
ziplist是由一系列特殊编码的连续内存块组成的顺序型数据结构,一个ziplist可以包含任意多个entry,而每一个entry又可以保存一个字节数组或者一个整数值。
ziplist和linkedlist最大的区别是ziplist不存储指向上一个节点和下一个节点的指针,存储的是上一个节点的长度和当前节点的长度,牺牲了部分读写性能来换取高效的内存利用率,是一种时间换空间的思想。
ziplist适用于字段个数少和字段值少的场景。
ziplist存储结构
entry存储结构
prevlen
encoding
encoding属性存储了当前entry所保存数据的类型以及长度。encoding长度为1字节,2字节或者5字节长。前面我们提到,每一个entry中可以保存字节数组和整数,而encoding属性的第1个字节就是用来确定当前entry存储的是整数还是字节数组。当存储整数时,第1个字节的前两位总是11,而存储字节数组时,则可能是00、01和10。
- 当存储整数时,第1个字节的前2位固定为11,其他位则用来记录整数值的类型或者整数值:
- 当存储字节数组时,第1个字节的前2位为00、01或者10,其他位则用来记录字节数组的长度:
entry-dataentry-data
:具体数据。当存储小整数时,encoding
就是数据本身,此时没有entry-data
部分,没有entry-data
部分之后的ziplist
结构如下:
ziplist连锁更新问题