1、压缩列表的存储结构
zlbytes:压缩列表的字节长度,占4个字节,因此压缩列表最多有2的32次-1个字节。
zltail:压缩列表尾元素相对于压缩列表起始地址的偏移量,占4个字节。
zllen:压缩列表的元素个数,占2个字节。zllen无法存储元素个数超过65535的压缩列表,
必须遍历整个压缩列表才能获取到元素个数。
entry:压缩列表的元素,可以是字节数组或整数,长度不限。
zlend:压缩列表的结尾,占1个字节,恒为0xFF。
假设unsigned char *zl指向压缩列表首地址,解读一下下面的宏定义;
zl指向zlbytes字段
#define ZIPLIST_BYTES(zl) (*((uint32_t*)(zl)))
指向zltail字段
#define ZIPLIST_TAIL_OFFSET(zl) (*((uint32_t*)((zl)+sizeof(uint32_t))))
指向尾元素首地址
#define ZIPLIST_ENTRY_TAIL(zl) ((zl)+intrev32ifbe(ZIPLIST_TAIL_OFFSET(zl)))
指向zllen字段
#define ZIPLIST_LENGTH(zl) (*((uint16_t*)((zl)+sizeof(uint32_t)*2)))
压缩列表最后一个字节
#define ZIPLIST_ENTRY_END(zl) ((zl)+intrev32ifbe(ZIPLIST_BYTES(zl))-1)
#define ZIPLIST_HEADER_SIZE (sizeof(uint32_t)*2+sizeof(uint16_t))
#define ZIPLIST_END_SIZE (sizeof(uint8_t))
2、压缩列表元素的编码结构
previous_entry_length:表示前一个元素的字节长度,占1个字节或5个字节(当前一个元素
的长度小于254字节时,用1字节表示,大于等于254字节时用5个字节表示。其中第一个字节固定
为0xFE,后4个字节表示元素的长度)
encoding:表示当前元素的编码,content存储的数据类型(整数或字节数组),长度可变见下图
content:存储数据内容
3、结构体
typedef struct zlentry {
unsigned int prevrawlensize; previous_entry_length的长度
unsigned int prevrawlen;previous_entry_length存储的内容
unsigned int lensize; encoding的长度
unsigned int len; 元素数据内容的长度
unsigned int headersize;当前元素的首部长度
unsigned char encoding; 数据类型
unsigned char *p; 当前元素的首地址
} zlentry;
创建空的压缩列表需要11(4+4+2+1)个字节
type:OBJ_LIST
encoding:quicklist和ziplist
执行lpush list1 jun(第一次)
验证增加了136字节。
sizeof(quicklist)=40
sizeof(quicklistNode)=32
sizeof(dictEntry)=24
sizeof(sdshdr8)= 3+1+5=9(16)
ziplist的大小11字节,分配器分配16字节
ziplist中的每一个zlentry,jun本身3个字节,encoding的长度1字节,前一个元素的长度1字节
继续执行lpush list1 wei
验证新增8字节
执行lpush list2 jun
验证增加了136字节。
typedef struct quicklist {
quicklistNode *head;
quicklistNode *tail;
unsigned long count; /* total count of all entries in all ziplists */
unsigned long len; /* number of quicklistNodes */
int fill : QL_FILL_BITS; /* fill factor for individual nodes */
unsigned int compress : QL_COMP_BITS; /* depth of end nodes not to compress;0=off */
unsigned int bookmark_count: QL_BM_BITS;
quicklistBookmark bookmarks[];
} quicklist;
typedef struct quicklistNode {
struct quicklistNode *prev;
struct quicklistNode *next;
unsigned char *zl;
unsigned int sz; /* ziplist size in bytes */
unsigned int count : 16; /* count of items in ziplist */
unsigned int encoding : 2; /* RAW==1 or LZF==2 */
unsigned int container : 2; /* NONE==1 or ZIPLIST==2 */
unsigned int recompress : 1; /* was this node previous compressed? */
unsigned int attempted_compress : 1; /* node can't compress; too small */
unsigned int extra : 10; /* more bits to steal for future usage */
} quicklistNode;
typedef struct quicklistBookmark {
quicklistNode *node;
char *name;
} quicklistBookmark;
2、相关操作
三个阻塞操作
blpop
brpop
brpoplpush
从左边操作
lindex
linsert
llen
lpop
lpush
lpushx
lrange
lrem
lset
ltrim
从右边操作
rpop
rpoplpush
rpush
rpushx