Redis-字典(hash表的底层实现)


字典,又称为符号表、关联数组或映射,是一种保存键值对的抽象数据结构。字典中每个键都是独一无二的,可以根据键对键值对进行操作。Redis所使用的C语言并没有内置字典,因此Redis构建了自己的字典实现。

Redis的数据库就是使用字典来作为底层实现的,对数据库的增删改查也是构建在对字典的操作之上的。

例如,SET msg "hello world",这个键值对就是保存在代表数据库字典里面的。

除了用来表示数据库之外,字典还是哈希键的底层实现之一,当一个哈希键包含的键值对比较多,又或键值对中的元素都是比较长的字符串时,Redis就会使用字典作为哈希键的底层实现。

1. 字典的实现

Redis的字典使用哈希表作为底层实现,一个哈希表里面可以有多个哈希表节点,而每个哈希表节点只能保存一个键值对。

1.1 哈希表

  • Redis 字典所使用的哈希表由 dict.h/dictht 结构定义:
typedef struct dictht {

    // 哈希表数组,每个元素都是一个指向 dict.h/dictEntry 结构的指针, 每个 dictEntry 结构保存着一个键值对。
    dictEntry **table;

    // 哈希表大小,table 数组的大小
    unsigned long size;

    // 哈希表大小掩码,用于计算索引值
    // 总是等于 size - 1, 这个属性和哈希值一起决定一个键应该被放到 table 数组的哪个索引上面。
    unsigned long sizemask;

    // 该哈希表已有节点的数量
    unsigned long used;

} dictht;

下图是一个空的哈希表
在这里插入图片描述

1.2 哈希表节点

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

    // 键
    void *key;

    // 值可以是一个指针, 或者是一个 uint64_t 整数, 又或者是一个 int64_t 整数。
    union {
        void *val;
        uint64_t u64;
        int64_t s64;
    } v;

    // 指向下个哈希表节点,形成链表,用解决hash冲突
    struct dictEntry *next;

} dictEntry;

下图是将两个索引值相同的键k1和k0连接在一起。
在这里插入图片描述

1.3 字典

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

typedef struct dict {

    // 类型特定函数
    dictType *type;

    // 私有数据
    void *privdata;

    // 哈希表
    dictht ht[2];

    // rehash 索引
    // 当 rehash 不在进行时,值为 -1
    int rehashidx; /* rehashing not in progress if rehashidx == -1 */

} dict;
  • type 属性是一个指向 dictType 结构的指针, 每个 dictType 结构保存了一簇用于操作特定类型键值对的函数, Redis 会为用途不同的字典设置不同的类型特定函数。
typedef struct dictType {

    // 计算哈希值的函数
    unsigned int (*hashFunction)(const void *key);

    // 复制键的函数
    void *(*keyDup)(void *privdata, const void *key);

    // 复制值的函数
    void *(*valDup)(void *privdata, const void *obj);

    // 对比键的函数
    int (*keyCompare)(void *privdata, const void *key1, const void *key2);

    // 销毁键的函数
    void (*keyDestructor)(void *privdata, void *key);

    // 销毁值的函数
    void (*valDestructor)(void *privdata, void *obj);

} dictType;
  • ht 属性是一个包含两个项的数组, 数组中的每个项都是一个 dictht 哈希表, 一般情况下, 字典只使用 ht[0] 哈希表, ht[1] 哈希表只会在对 ht[0] 哈希表进行 rehash 时使用。
  • 除了 ht[1] 之外, 另一个和 rehash 有关的属性就是 rehashidx : 它记录了 rehash 目前的进度, 如果目前没有在进行 rehash , 那么它的值为 -1 。

一个普通状态下(没有进行 rehash)的字典:
在这里插入图片描述
hash算法、rehash及如何解决hash冲突,会在下一篇文章中记录。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值