1、早期版本存储list集合,采用ziplist和linkedlist,但由于链表的附加空间高,prev和next就要占去16个字节,而且每个节点的内存都要单独分配,会加剧内存的碎片化,所以后面的版本对结构进行了改造,使用快速列表(quicklist)
1)实例
> rpush codehole go java python (integer) 3 > debug object codehole Value at:0x7fec2dc2bde0 refcount:1 encoding:quicklist serializedlength:31 lru:6101643 lru_seconds_idle:5 ql_nodes:1 ql_avg_node:3.00 ql_ziplist_max:-2 ql_compressed:0 ql_uncompressed_size:29 |
quicklist是ziplist和linklist的混合体,他将linkedlist按段切分,每一段使用ziplist紧凑存储,东哥ziplist之间使用双向指针窜接起来,如下图所示
2)quicklist结构体
struct quicklist { quicklistNode* head; quicklistNode* tail; long count; // 元素总数 int nodes; // ziplist 节点的个数 int compressDepth; // LZF 算法压缩深度 ... } struct quicklistNode { quicklistNode* prev; quicklistNode* next; ziplist* zl; // 指向压缩列表 int32 size; // ziplist 的字节总数 int16 count; // ziplist 中的元素数量 int2 encoding; // 存储形式 2bit,原生字节数组还是 LZF 压缩存储 ... } struct ziplist_compressed { int32 size; byte[] compressed_data; } struct ziplist { ...//上诉有 }
|
Redis为了进一步节省空间,还会对ziplist使用LZF算法进行压缩存储,还可以选择压缩深度。
2、配置参数list-max-ziplist-size:控制每个ziplist存元素的数量,quicklist内部默认单个ziplist长度为8k字节
3、配置参数 list-compress-depth:压缩实际深度
1)quicklist默认压缩深度是0,即不压缩
2)为了支持快速的push/pop,quicklist首尾俩个ziplist不压缩,此时深度为1
3)quicklist首尾第一个ziplist及第二个都不压缩,那么该参数为2,以此类推。