redis数据结构——快速列表

quicklist.c - A doubly linked list of ziplists

通过上面这句话可以了解到,快速列表是由双向压缩链表实现的。

先来看看quicklist的结构:

typedef struct quicklist {
    quicklistNode *head;        /* 指向头结点 */
    quicklistNode *tail;        /* 指向尾结点 */
    unsigned long count;        /* entry个数 */
    unsigned long len;          /* 节点个数 */
    int fill : 16;              /* 单个节点的充填因子 */
    /* compress=-1时,说明不能压缩;否则就是在quicklist的末尾没有压缩的节点数量;
     * =0时,表示不压缩
     */                                 
    unsigned int compress : 16;
} quicklist;

再看看quicklistNode的结构:

typedef struct quicklistNode {
    struct quicklistNode *prev;  /* 指向当前节点的前一个节点 */
    struct quicklistNode *next;  /* 指向当前节点的后一个节点 */
    unsigned char *zl;           /* 指针,指向一个ziplist */
    unsigned int sz;             /* ziplist的大小 */
    unsigned int count : 16;     /* 计数 */
    unsigned int encoding : 2;   /* 编码;RAW==1,LZF==2 */
    unsigned int container : 2;  /* 容器;NONE==1,ZIPLIST==2 */
    /* 这个节点是否被压缩过? 如果节点在使用时,是临时解压,则为true*/
    unsigned int recompress : 1;
    unsigned int attempted_compress : 1; /* 节点太小则不能压缩 */
    unsigned int extra : 10; /* 冗余字段 */
} quicklistNode;

那么在什么情况下会进行压缩呢?来看看压缩方法:

/* 只会压缩没有被压缩的节点 */
#define quicklistCompressNode(_node)                                           
    do {                                                                       
        if ((_node) && (_node)->encoding == QUICKLIST_NODE_ENCODING_RAW) {     
            __quicklistCompressNode((_node));                                  
        }                                                                      
    } while (0)

这里压缩的具体实现在_quicklistCompressNode方法中:

/* 压缩成功返回1,压缩失败或者列表太小了不用压缩则返回0 */
REDIS_STATIC int __quicklistCompressNode(quicklistNode *node) {
#ifdef REDIS_TEST
    node->attempted_compress = 1;
#endif

    /* 小于48字节,不需要用到压缩 */
    if (node->sz < MIN_COMPRESS_BYTES)
        return 0;
    /* 否则分配空间,这是数据结构是quicklistLZF */
    quicklistLZF *lzf = zmalloc(sizeof(*lzf) + node->sz);

    /* 压缩失败或者不用压缩,那么需要释放lzf的空间,并且返回0 */
    if (((lzf->sz = lzf_compress(node->zl, node->sz, lzf->compressed,
                                 node->sz)) == 0) ||
        lzf->sz + MIN_COMPRESS_IMPROVE >= node->sz) {
        zfree(lzf);
        return 0;
    }
    /* 以下操作就是压缩节点,将数据结构改成quicklistLZF */
    lzf = zrealloc(lzf, sizeof(*lzf) + lzf->sz);
    zfree(node->zl);
    node->zl = (unsigned char *)lzf;
    node->encoding = QUICKLIST_NODE_ENCODING_LZF;
    node->recompress = 0;
    return 1;
}

可见,在压缩之后,数据结构不再是quicklist而是quicklistLZF,它的结构如下:

/* 没有被压缩的长度存放在quicklistNode节点的sz属性中
 * 当节点被压缩的时候,这个节点的数据结构就是quicklistLZF */
typedef struct quicklistLZF {
    unsigned int sz; /* compressed数组长度 */
    char compressed[]; 
} quicklistLZF;

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值