概述

上篇博客我简单整理了 redis 中链表的实现原理。本篇博客我打算就哈希类型简单整理一下。


redis 数据类型

redis 有以下五种常用的数据类型:

  • String:字符串类型
  • Hash:哈希类型
  • list:链表类型
  • set:集合类型
  • zSet:有序集合类型

1、哈希表

redis 中哈希表使用头文件 dict.h 中的 dictht 结构体定义:

typedef struct dictht {
    // 哈希表数组
    dictEntry **table;
    // 哈希表大小
    unsigned long size;
    //哈希表大小掩码,用于计算索引值
    //总是等于size-1
    unsigned long sizemask;
    // 该哈希表已有节点的数量
    unsigned long used;
} dictht;
  • table 属性是一个数组,数组元素都是指向 dictEnty 结构的指针,每个 dictEntry 都包含一个键值对
  • size 属性记录哈希表的大小,即 table 数组的大小
  • sizemask 的值总等于 size-1,这个属性和 hash 值一起决定键被放到数组的哪个索引上
  • used 属性记录已有节点的数量

键值对:一个键可以和一个值进行关联,这些关联的键和值就称为键值对。

下面我们看一张大小为4的空哈希表结构图:

redis的ha redis的hash实现原理_redis


哈希表节点

哈希表节点使用 dictEntry 表示,它的结构如下所示:

typedef struct dictEntry {
    // 键
    void *key;
    // 值
    union{
        void *val;
        uint64_tu64;
        int64_ts64;
    } v;
    // 指向下个哈希表节点,形成链表
    struct dictEntry *next;
} dictEntry;
  • key 属性表示键值对中的键
  • v 属性保存键值对中的值,值可以是一个指针,也可以是 uint64_t 类型整数,还可以是 int64_t 类型整数
  • next 属性是指向另一个节点的指针,通过它可以将 hash 值相同的键值对连接在一起,避免冲突

下面我给出大小为4,包含两个相同 hash 值节点的哈希表示意图:

redis的ha redis的hash实现原理_redis_02


从这里也就可以看出,redis 哈希表的实现也是通过数组+链表,和之前我们介绍的 hashmap 相同。


字典与哈希表

字典:字典是一个抽象概念,它是描述键映射到值的一般概念。

也就是说字典表有很多种实现方式,哈希表是字典的一种实现方式。redis 中字典底层是通过哈希表实现的,关于哈希表更多细节,我打算放到下一篇博客详细介绍,一来是想区分字典和哈希表的概念,二来是尽可能让每篇博客都专注一些,尽可能不搞混


参考:
《redis设计与实现》黄健宏著