美文网首页
05-Redis的内存对象及内部编码_List

05-Redis的内存对象及内部编码_List

作者: yakun0622 | 来源:发表于2020-03-31 10:13 被阅读0次

    列表(list)用来存储多个有序的元素; 一个列表可以存储2^32-1个元素。
    Redis中的列表支持两端插入和弹出,并可以获得指定位置(或范围)的元素,可以充当数组、队列、栈等。

    1 内部编码
    列表的内部编码可以是压缩列表(ziplist)或双端链表(linkedlist)

    • 双端链表
      与双链表定义一致,引入了链表节点,并在此基础上增加头尾节点构建双端链表
      链表节点listNode如下定义:
    /* Node, List, and Iterator are the only data structures used currently. */  
    /* 
     * 链表节点 
     */  
    typedef struct listNode {  
        // 前驱节点  
        struct listNode *prev;  
        // 后继节点  
        struct listNode *next;  
        // 值  
        void *value;  
    } listNode;  
    

    链表如下定义:

    /* 
    * 链表 
    */  
    typedef struct list {  
       // 表头指针  
       listNode *head;  
       // 表尾指针  
       listNode *tail;  
       // 节点数量  
       unsigned long len;  
       // 复制函数  
       void *(*dup)(void *ptr);  
       // 释放函数  
       void (*free)(void *ptr);  
       // 比对函数  
       int (*match)(void *ptr, void *key);  
    } list;  
    

    双端链表结构如下图所示:


    在这里插入图片描述

    通过图中可以看出,双端链表同时保存了表头指针和表尾指针,并且每个节点都有指向前和指向后的指针;链表中保存了列表的长度;dup、free和match为节点值设置类型特定函数,所以链表可以用于保存各种不同类型的值。而链表中每个节点指向的是type为字符串的redisObject。

    • 压缩列表
      压缩列表是Redis为了节约内存而开发的,是由一系列特殊编码的连续内存块(而不是像双端链表一样每个节点是指针)组成的顺序型数据结构。
      压缩列表的结构
    • zlbytes记录整个压缩列表占用的内存字节数,在对压缩列表进行内存重分配或计算
    • zlend的位置时使用
    • zltail记录压缩列表尾节点距离压缩列表的起始地址有多少字节,通过这个偏移量,可以直接确定尾节点的位置
    • zllen记录压缩列表包含的节点数量
    • entryX表示各种节点,数量和长度不一定
    • zlend用于标记压缩列表的末端。

    如图,如果有一个指针p指向该压缩列表,则尾巴节点的长度就是指针加上偏移量179(十六进制0xb3=16*11+3=179),列表的长度zllen为5,表示压缩列表包含5个节点。zlbytes为0xd2表示压缩列表的总长为210字节。

    在这里插入图片描述

    由上可知,每个压缩列表的节点可以保存一个字节数组或者一个整数值,那么每个节点肯定也有自己的结构。

    与双端链表相比,压缩列表可以节省内存空间,但是进行修改或增删操作时,复杂度较高
    因此当节点数量较少时,可以使用压缩列表;但是节点数量多时,还是使用双端链表划算

    压缩列表不仅用于实现列表,也用于实现哈希、有序列表;使用非常广泛。

    相关文章

      网友评论

          本文标题:05-Redis的内存对象及内部编码_List

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