redis-list解读

156 阅读3分钟

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;

创建空的压缩列表需要114+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