概述
上篇博客我简单整理了 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的空哈希表结构图:
哈希表节点
哈希表节点使用 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 哈希表的实现也是通过数组+链表,和之前我们介绍的 hashmap 相同。
字典与哈希表
字典:字典是一个抽象概念,它是描述键映射到值的一般概念。
也就是说字典表有很多种实现方式,哈希表是字典的一种实现方式。redis 中字典底层是通过哈希表实现的,关于哈希表更多细节,我打算放到下一篇博客详细介绍,一来是想区分字典和哈希表的概念,二来是尽可能让每篇博客都专注一些,尽可能不搞混
参考:
《redis设计与实现》黄健宏著