zoukankan      html  css  js  c++  java
  • redis数据结构-链表,压缩表,快速表

    大纲:

    1. 双向链表-list
    2. 压缩表-ziplist
    3. 快速表-quicklist

    一、双向链表-list

    redis早期版本处理list用的就是双向链表

    struct listNode{
        struct listNode *prev; //前一个结点
        struct listNode *nenxt; //下一个结点
        void *value;//节点的值
    }
    
    struct list {
        listNode *head; //头结点
        listNode *tail; //头结点
        long len;//节点数量
    }

    二、压缩表-ziplist

    用数组的形式模仿实现了双向链表

    2.1ziplist组成

    • zlbytes: ziplist的大小(单位: 字节)
    • zltail: ziplist最后一个节点的偏移量,有ziplist守地址,有偏移量可以定位最后一个entry用于反向遍历
    • zllen: ziplist的节点(entry)个数
    • entry: 节点
    • zlend: 值为0xFF,ziplist的结尾

    2.2entry的组成

    data就是实际存放的数据

    prelength是前结点的大小,也是用与反向遍历的,如果前结点小于254字节,则entry中prelength占用1个字节来记录,如果大于等于254,prelength占用5个字节,第一字节固定254,后4个字节表示大小

    encoding用于表示data存储的数据类型和数据大小

     最后1111xxxx表示超小数0-12。0000,1110,1111被占掉了,xxxx可以表示1-13,实际表示的值再-1。

     上图中pppqqqrrrsssttt都是用来表示字符串大小的

    三、快速表-quicklist

    压缩表的特点是结构紧凑占用内存少,连续内存读写块,但缺点是,频繁增加导致realoc重新分配内存,消耗性能。

    链表的特点是存储前后指针(浪费一定空间),但增加删除、删除结点不用内存重分配,但存储的内存非连续,读写性能偏低。

    结合上述两种结构的优点设计出了快速表:快速表示一个双向链表,只不过每一个节点的值是一个压缩表。

    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 */ LZF为压缩算法
        unsigned int container : 2;  /* NONE==1 or ZIPLIST==2 */ 目前只有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 quicklistLZF {
        unsigned int sz; /* LZF size in bytes*/
        char compressed[]; //压缩后的数据保存在字节数组中(c中没有byte类型,一个char占1字节,所以用char表示)
    } quicklistLZF;
    
    typedef struct quicklist {
        quicklistNode *head;
        quicklistNode *tail;
        unsigned long count;        /* total count of all entries in all ziplists */
        unsigned int len;           /* number of quicklistNodes */
        int fill : 16;              /* fill factor for individual nodes  一个配置项list-max-ziplist-size,规定了ziplist中有多少个entry,当值为(-1~-5)时,表示一个ziplist的大小(4k~64k),越接近1越向一个链表,越接近无穷大越像一个压缩表 */
        unsigned int compress : 16; /* depth of end nodes not to compress;0=off   一个配置项list-compress-depth,规定了链表两端多少个quicklistNode不被压缩,经研究链表的头尾节点是使用率最高的,因此中间不常被访问的结点应该被压缩*/
    } quicklist;
  • 相关阅读:
    Linux常用命令
    PHP中的 extends与implements 区别
    IDEA链接MongoDB数据库-实现增删改查
    在IDEA中用三个jar包链接MongoDB数据库——实现增删改查
    MongoDB修改账号密码
    进入 MongoDB
    MongoDB安装
    解决{"error_code":110,"error_msg":"Access token invalid or no longer valid"}
    毕设进度(10.29)
    毕设进度(10.28)
  • 原文地址:https://www.cnblogs.com/liuboyuan/p/14720096.html
Copyright © 2011-2022 走看看