美文网首页
Redis笔记之快速列表

Redis笔记之快速列表

作者: slxixiha | 来源:发表于2021-08-25 22:20 被阅读0次

    quicklist 实际上是 zipList 和 linkedList 的混合体,它将 linkedList 按段切分,每一段使用 zipList 来紧凑存储,多个 zipList 之间使用双向指针链接。

    快速列表的定义

    列表的节点
    // quicklist.h
    /* quicklistNode is a 32 byte struct describing a ziplist for a quicklist.
     * We use bit fields keep the quicklistNode at 32 bytes.
     * count: 16 bits, max 65536 (max zl bytes is 65k, so max count actually < 32k).
     * encoding: 2 bits, RAW=1, LZF=2.
     * container: 2 bits, NONE=1, ZIPLIST=2.
     * recompress: 1 bit, bool, true if node is temporary decompressed for usage.
     * attempted_compress: 1 bit, boolean, used for verifying during testing.
     * extra: 10 bits, free for future use; pads out the remainder of 32 bits */
    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;
    
    • prev: 指向链表前一个节点的指针。
    • next: 指向链表后一个节点的指针。
    • zl: 数据指针。如果当前节点的数据没有压缩,那么它指向一个ziplist结构;否则,它指向一个quicklistLZF结构。
    • sz: 表示zl指向的ziplist的总size(包括zlbytes, zltail, zllen, zlend和各个数据项)。注意:如果ziplist被压缩了,这个sz的值仍然是压缩前的ziplist大小。
    • count: 表示ziplist里面包含的数据项个数。
    • encoding: 表示ziplist是否压缩了(以及用了哪个压缩算法)。目前只有两种取值。
    • container: 是一个预留字段。本来设计是用来表明一个quicklist节点下面是直接存数据,还是使用ziplist存数据,或者用其它的结构来存数据(用作一个数据容器,所以叫container)。但是,在目前的实现中,这个值是一个固定的值2,表示使用ziplist作为数据容器。
    • recompress: 使用例如index命令查看某一项本来压缩的数据时,需要把数据暂时解压,这时设置recompress=1做标记解压状态,后面有机会再压缩数据。
    • attempted_compress: 这个值只对Redis的自动化测试程序有用。
    • extra: 其它扩展字段,暂时不管。
    压缩后的ziplist
    // quicklist.h
    /* quicklistLZF is a 4+N byte struct holding 'sz' followed by 'compressed'.
     * 'sz' is byte length of 'compressed' field.
     * 'compressed' is LZF data with total (compressed) length 'sz'
     * NOTE: uncompressed length is stored in quicklistNode->sz.
     * When quicklistNode->zl is compressed, node->zl points to a quicklistLZF */
    typedef struct quicklistLZF {
        unsigned int sz; /* LZF size in bytes*/
        char compressed[];
    } quicklistLZF;
    

    quicklistLZF结构表示一个被压缩过的ziplist.

    quicklist定义
    // quicklist.h
    /* quicklist is a 40 byte struct (on 64-bit systems) describing a quicklist.
     * 'count' is the number of total entries.
     * 'len' is the number of quicklist nodes.
     * 'compress' is: 0 if compression disabled, otherwise it's the number
     *                of quicklistNodes to leave uncompressed at ends of quicklist.
     * 'fill' is the user-requested (or default) fill factor.
     * 'bookmakrs are an optional feature that is used by realloc this struct,
     *      so that they don't consume memory when not used. */
    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;
    
    • head: 指向头节点(左侧第一个节点)的指针。
    • tail: 指向尾节点(右侧第一个节点)的指针。
    • count: 所有ziplist数据项的个数总和。
    • len: quicklist节点的个数。
    • fill: 16bit,ziplist大小设置,存放list-max-ziplist-size的值。
    • compress: 16bit,节点压缩深度值,存放list-compress-depth的值。
    • bookmark_count:4bit,bookmark的计数值。
    • bookmarks:bookmark列表。
    bookmark的定义
    // quicklist.h
    /* Bookmarks are padded with realloc at the end of of the quicklist struct.
     * They should only be used for very big lists if thousands of nodes were the
     * excess memory usage is negligible, and there's a real need to iterate on them
     * in portions.
     * When not used, they don't add any memory overhead, but when used and then
     * deleted, some overhead remains (to avoid resonance).
     * The number of bookmarks used should be kept to minimum since it also adds
     * overhead on node deletion (searching for a bookmark to update). */
    typedef struct quicklistBookmark {
        quicklistNode *node;
        char *name;
    } quicklistBookmark;
    
    bookmark用于加速遍历quicklist的node。它只用于大数据量结点的quicklist中,在这种情况下少量的bookmark的内存使用可以被忽略不计。
    

    快速列表的结构图

    快速列表1.PNG 快速列表2.PNG

    参考文章
    https://www.cnblogs.com/hunternet/p/12624691.html

    相关文章

      网友评论

          本文标题:Redis笔记之快速列表

          本文链接:https://www.haomeiwen.com/subject/whhriltx.html