Redis数据结构之QuickList

Redis数据结构之QuickList

从ZipList到QuickList

在ZipList,由于申请的空间是连续的,所以ZipList时比较节省内存的,但是同时带来的一个问题,如果申请内存占用较多,数据量较大时,就会导致无法保证申请到够大的内存空间,申请空间效率降低;

申请内存占用多的情况下可以限制ZipList的长度和entry大小;
数据量较大的情况下可以创建多个ZipList分片来存储数据;

那么多个ZipList之间如何建立联系?显然,链表是个不错的选择。

QuickList就是这样的一个双端链表,链表中每个节点都是一个ZipList;

QuickList的结构

  • QuickList链表结构:
typedef struct quicklist {
	//头节点指针
	quicklistNode *head;
	//尾节点指针
	quicklistNode *tail;
	//所有ziplist的entry的数量
	unsigned long count;
	// ziplists总数量
	unsigned long len;
	// ziplist的entry上限,默认值-2
	int fill : QL_FILL_BITS;
	//首尾不压缩的节点数量
	unsigned int compress : QL_COMP_BITS;
	//内存重分配时的书签数量及数组,一般用不到
	unsigned int bookmark_count: QL_BM_BITS;
	quicklistBookmark bookmarks[];
} quicklist;
  • QuickList链表节点:
typedef struct quicklistNode {
	//前一个节点指针
	struct quicklistNode *prev;
	//下一个节点指针
	struct quicklistNode *next;
	//当前节点的ZipList指针
	unsigned char *zl;
	//当前节点的ZipList的字节大小
	unsigned int sz;
	//当前节点的ZipList的entry个数
	unsigned int count : 16;
	//编码方式:1,ZipList; 2,lzf压缩模式
	unsigned int encoding : 2;
	//数据容器类型(预留):1,其它;2,ZipList
	unsigned int container : 2;
	//是否被解压缩。1:则说明被解压了,将来要重新压缩
	unsigned int recompress : 1;
	unsigned int attempted_compress : 1;//测试用
	unsigned int extra : 10;  /* 预留字段*/
}quicklistNode;
  • QuickList和ZipList之间的结构
    Redis数据结构之QuickList_第1张图片

QuickList优化

  • 为了避免ziplist中的entry数量过多,Redis提供了相关配置用于线程quicklist中ziplist大小,配置项 list-max-ziplist-size :

      如果为正 ,则代表Ziplist的entry允许的最大个数。
      如果为负,则代表Ziplist的最大内存大小,5种情况:(默认-2)  
      -1 :每个ziplist不超过4kb
      -2 :每个ziplist不超过8kb
      -3 :每个ziplist不超过16kb
      -4 :每个ziplist不超过32kb
      -5 :每个ziplist不超过64kb
    
  • 除了控制Ziplist大小,Quicklist还可以对节点的Ziplist进行压缩,通过配置list-compress-depth来控制。因为链表一般来说首尾访问较多,所以首尾是不压缩的,这个参数是控制首尾不压缩的节点个数。

      0 :默认值,不压缩。
      1:   表示Quicklist首尾个1个节点不压缩,中间节点压缩。
      2:   表示Quicklist首尾个2个节点不压缩,中间节点压缩。
    

你可能感兴趣的:(redis,数据结构,数据库)