字典的实现

    接下来的三个小节将分别介绍 Redis 的哈希表、哈希表节点、以及字典的实现。

    Redis 字典所使用的哈希表由 结构定义:

    table 属性是一个数组,数组中的每个元素都是一个指向 dict.h/dictEntry 结构的指针,每个 dictEntry 结构保存着一个键值对。

    size 属性记录了哈希表的大小,也即是 table 数组的大小,而 used 属性则记录了哈希表目前已有节点(键值对)的数量。

    sizemask 属性的值总是等于 size - 1 ,这个属性和哈希值一起决定一个键应该被放到 table 数组的哪个索引上面。

    哈希表节点使用 dictEntry 结构表示,每个 结构都保存着一个键值对:

    key 属性保存着键值对中的键,而 v 属性则保存着键值对中的值,其中键值对的值可以是一个指针,或者是一个 uint64_t 整数,又或者是一个 int64_t 整数。

    next 属性是指向另一个哈希表节点的指针,这个指针可以将多个哈希值相同的键值对连接在一次,以此来解决键冲突(collision)的问题。

    举个例子,图 4-2 就展示了如何通过 next 指针,将两个索引值相同的键 k1k0 连接在一起。

    Redis 中的字典由 dict.h/dict 结构表示:

    type 属性和 privdata 属性是针对不同类型的键值对,为创建多态字典而设置的:

    • privdata 属性则保存了需要传给那些类型特定函数的可选参数。

    ht 属性是一个包含两个项的数组,数组中的每个项都是一个 dictht 哈希表,一般情况下,字典只使用 ht[0] 哈希表,ht[1] 哈希表只会在对 ht[0] 哈希表进行 rehash 时使用。

    除了 ht[1] 之外,另一个和 rehash 有关的属性就是 rehashidx :它记录了 rehash 目前的进度,如果目前没有在进行 rehash ,那么它的值为 -1

    图 4-3 展示了一个普通状态下(没有进行 rehash)的字典: