redis hash表设计 redis hash怎么实现_数组

你好,是我琉忆。

上一篇我们主要介绍了String和List的底层实现原理,今天我们来说说Hash的数据结构。

哈希作为我们常见的一种数据结构,那么在Redis中它是怎么实现的呢?

01


Hash的数据结构

Redis 中的hash,内部是由 HashTable 或者 ziplist实现的。而HashTable 的内部结构是由数组加链表的二维结构实现的。它包含若干个 key-value,key 不重复。

首先我们来看看HashTable内部实现结构:

实现的流程:

redis hash表设计 redis hash怎么实现_数组_02

实现的源码:

/* * 哈希表节点 */typedef struct dictEntry {    // 键    void *key;    // 值    union {        void *val;        uint64_t u64;        int64_t s64;    } v;    // 指向下个哈希表节点,形成链表    struct dictEntry *next;} dictEntry;/* * 哈希表 *  * 每个字典都使用两个哈希表,从而实现渐进式 rehash 。 */typedef struct dictht {    // 哈希表数组    dictEntry **table;    // 哈希表大小    unsigned long size;    // 哈希表大小掩码,用于计算索引值    // 总是等于 size - 1    unsigned long sizemask;    // 该哈希表已有节点的数量    unsigned long used;} dictht;

那么HashTable是如何实现扩容的呢?

02

HashTable的扩容流程

扩容流程如下:

redis hash表设计 redis hash怎么实现_Redis_03

首先我们要知道,Redis 扩容采用的是渐进式 Hash 的方式进行扩容。原来的 hash 表是 h[0],然后加倍 size 生成一个新的 hash 表 h[1],然后在定时任务中,渐渐地将 h[0] 中的内容迁移到 h[1] 中。

执行下面的操作时,内部的实现步骤: 

  • 读操作:先去 h[0] 中找,找不到再去 h[1] 中去找。
  • 写操作:直接写在 h[1] 中
  • 删除操作和读操作类似

根据上面的流程,我们来按步骤看看它的内部扩容实现:

需要知道的是:哈希表内部是由数组加链表实现的。

步骤一:新建一个 H[1],为字典 h[1] 分配空间,hash 表初始化的状态就有一个 h[0] 和 h[1]。

int _dictInit(dict *d, dictType *type,        void *privDataPtr){    // 初始化两个哈希表的各项属性值    // 但暂时还不分配内存给哈希表数组    _dictReset(&d->ht[0]);    _dictReset(&d->ht[1]);    // 设置类型特定函数    d->type = type;    // 设置私有数据    d->privdata = privDataPtr;    // 设置哈希表 rehash 状态    d->rehashidx = -1;    // 设置字典的安全迭代器数量    d->iterators = 0;    return DICT_OK;}

具体的实现在 dict.c 中的 dictExpand 这个方法。此时 dicth[1] 指向一个数组table[]。

哈希表初始状态:

redis hash表设计 redis hash怎么实现_Redis_04

为 h[1] 分配空间:

redis hash表设计 redis hash怎么实现_字典哈希表的实现原理_05

步骤二:将 h[0] 中的所有键值对,rehash 到 h[1] 上,rehash 是指重新计算哈希值和索引值。将键值对放到 h[1] 上面的指定位置。

redis hash表设计 redis hash怎么实现_PHP_06

步骤三:当h[0] 中包含的键值对都迁移到了 h[1] 上面,需要释放 h[1],并将 h[1] 设置为 h[0],并在 h[1] 新创建一个空白哈希表,为下次 rehash 准备。

redis hash表设计 redis hash怎么实现_Redis_07

自此Hash实现扩容。这就是哈希表完成一个完整的扩容过程。

zplist我们在下一篇和集合一起讲解。



redis hash表设计 redis hash怎么实现_字典哈希表的实现原理_08

 后话

    是否觉得小小的哈希不简单。学完这篇文章后是否有耳目一新又重新认识了一次哈希?希望你能够继续跟着我的步伐往后看,下一篇我们讲讲集合的数据结构。