您好,欢迎来到12图资源库!分享精神,快乐你我!我们只是素材的搬运工!!
  • 首 页
  • 当前位置:首页 > 开发 > WEB开发 >
    能够是目前最详细的Redis内存模型及运用解读(5)
    时间:2018-08-09 08:10 来源:网络整理 作者:网络 浏览:收藏 挑错 推荐 打印

    其中,单个字符串不能超过64字节,是为了便于一致分配每个节点的长度;这里的64字节是指字符串的长度,不包括SDS结构,由于紧缩列表运用延续、定长内存块存储字符串,不需求SDS结构指明长度。前面提到紧缩列表,也会强调长度不超过64字节,原理与这里相似。

    3、哈希

    (1)概略

    哈希(作为一种数据结构),不只是redis对外提供的5种对象类型的一种(与字符串、列表、集合、有序结兼并列),也是Redis作为Key-Value数据库所运用的数据结构。为了阐明的方便,在本文前面当运用“内层的哈希”时,代表的是redis对外提供的5种对象类型的一种;运用“外层的哈希”代指Redis作为Key-Value数据库所运用的数据结构。

    (2)外部编码

    内层的哈希运用的外部编码可以是紧缩列表(ziplist)和哈希表(hashtable)两种;Redis的外层的哈希则只运用了hashtable。

    紧缩列表前面已引见。与哈希表相比,紧缩列表用于元素个数少、元素长度小的场景;其优势在于集中存储,节省空间;同时,虽然关于元素的操作复杂度也由O(n)变为了O(1),但由于哈希中元素数量较少,因此操作的时间并没有清楚优势。

    hashtable:一个hashtable由1个dict结构、2个dictht结构、1个dictEntry指针数组(称为bucket)和多个dictEntry结构组成。

    正常状况下(即hashtable没有停止rehash时)各部分关系如下图所示:

    能够是目前最详细的Redis内存模型及运用解读

    图片改编自:《Redis设计与完成》

    下面从底层向上依次引见各个部分:

    dictEntry

    dictEntry结构用于保存键值对,结构定义如下:

    typedef struct dictEntry{ 

        void *key

        union

            void *val; 

            uint64_tu64; 

            int64_ts64; 

        }v; 

        struct dictEntry *next

    }dictEntry; 

    其中,各个属性的功用如下:

    key:键值对中的键;

    val:键值对中的值,运用union(即共用体)完成,存储的内容既能够是一个指向值的指针,也能够是64位整型,或无符号64位整型;

    next:指向下一个dictEntry,用于处置哈希抵触成绩

    在64位系统中,一个dictEntry对象占24字节(key/val/next各占8字节)。

    bucket

    bucket是一个数组,数组的每个元素都是指向dictEntry结构的指针。redis中bucket数组的大小计算规则如下:大于dictEntry的、最小的2^n;例如,假设有1000个dictEntry,那么bucket大小为1024;假设有1500个dictEntry,则bucket大小为2048。

    dictht

    dictht结构如下:

    typedef struct dictht{ 

        dictEntry **table

        unsigned long size

        unsigned long sizemask; 

        unsigned long used; 

    }dictht; 

    其中,各个属性的功用阐明如下:

    table属性是一个指针,指向bucket;

    size属性记载了哈希表的大小,即bucket的大小;

    used记载了已运用的dictEntry的数量;

    sizemask属性的值总是为size-1,这个属性和哈希值一同决议一个键在table中存储的位置。

    dict

    普通来说,经过运用dictht和dictEntry结构,便可以完成普通哈希表的功用;但是Redis的完成中,在dictht结构的下层,还有一个dict结构。下面阐明dict结构的定义及作用。

    dict结构如下:

    typedef struct dict{ 

        dictType *type; 

        void *privdata; 

        dictht ht[2]; 

        int trehashidx; 

    } dict; 

    其中,type属性和privdata属性是为了顺应不同类型的键值对,用于创立多态字典。

    ht属性和trehashidx属性则用于rehash,即当哈希表需求扩展或收缩时运用。ht是一个包含两个项的数组,每项都指向一个dictht结构,这也是Redis的哈希会有1个dict、2个dictht结构的缘由。通常状况下,一切的数据都是存在放dict的ht[0]中,ht[1]只在rehash的时分运用。dict停止rehash操作的时分,将ht[0]中的一切数据rehash到ht[1]中。然后将ht[1]赋值给ht[0],并清空ht[1]。

    因此,Redis中的哈希之所以在dictht和dictEntry结构之外还有一个dict结构,一方面是为了顺应不同类型的键值对,另一方面是为了rehash。

    (3)编码转换

    如前所述,Redis中内层的哈希既能够运用哈希表,也能够运用紧缩列表。

    只要同时满足下面两个条件时,才会运用紧缩列表:

    哈希中元素数量小于512个;

    哈希中一切键值对的键和值字符串长度都小于64字节。

    假设有一个条件不满足,则运用哈希表;且编码只能够由紧缩列表转化为哈希表,反方向则不能够。

    下图展现了Redis内层的哈希编码转换的特点:

    (责任编辑:admin)