Redis字典的实现 《Redis设计与实现》

实现字典的方法有很多种:
• 最简单的就是使用链表或数组,但是这种方式只适用于元素个数不多的情况下;
• 要兼顾高效和简单性,可以使用哈希表; // Hash无法实现稳定性
• 如果追求更为稳定的性能特征,并且希望高效地实现排序操作的话,则可以使用更为复 杂的平衡树;
在众多可能的实现中,Redis 选择了高效且实现简单的哈希表作为字典的底层实现

数据结构实现

dict.h/dict 给出了这个字典的定义

/* * 字典 * * 每个字典使用两个哈希表,用于实现渐进式 rehash */
 typedef struct dict {
// 特定于类型的处理函数
 dictType *type;
// 类型处理函数的私有数据 
void *privdata;
// 哈希表(2 个)
 dictht ht[2];
// 记录 rehash 进度的标志,值为-1 表示 rehash 未进行
 int rehashidx;
// 当前正在运作的安全迭代器数量
 int iterators;
} dict;

以下是用于处理 dict 类型的 API ,它们的作用及相应的算法复杂度:
在这里插入图片描述
注意 dict 类型使用了两个指针分别指向两个哈希表。
其中,0 号哈希表(ht[0])是字典主要使用的哈希表,而 1 号哈希表(ht[1])则只有在程序 对 0 号哈希表进行 rehash 时才使用。
接下来两个小节将对哈希表的实现,以及哈希表所使用的哈希算法进行介绍。

哈希表实现

字典所使用的哈希表实现由 dict.h/dictht 类型定义

/* * 哈希表 */
 typedef struct dictht {
// 哈希表节点指针数组(俗称桶,bucket)
 dictEntry **table;
// 指针数组的大小
 unsigned long size;
// 指针数组的长度掩码,用于计算索引值 
unsigned long sizemask;
// 哈希表现有的节点数量 
unsigned long used;
} dictht;

table 属性是一个数组,数组的每个元素都是一个指向 dictEntry 结构的指针。 每个 dictEntry 都保存着一个键值对,以及一个指向另一个 dictEntry 结构的指针:

/* * 哈希表节点 */ 
typedef struct dictEntry {
// 键
 void *key;
// 值 
union { void *val; uint64_t u64; int64_t s64; } v;
// 链往后继节点
 struct dictEntry *next;
} dictEntry;

next 属性指向另一个 dictEntry 结构,多个 dictEntry 可以通过 next 指针串连成链表,从 这里可以看出,**dictht 使用链地址法来处理键碰撞:**当多个不同的键拥有相同的哈希值时,哈 希表用一个链表将这些键连接起来。
下图展示了一个由 dictht 和数个 dictEntry 组成的哈希表例子:
在这里插入图片描述
如果再加上之前列出的 dict 类型,那么整个字典结构可以表示如下:
在这里插入图片描述
在上图的字典示例中,字典虽然创建了两个哈希表,但正在使用的只有 0 号哈希表,这说明字 典未进行 rehash 状态。

素材来自: 《Redis设计与实现》

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值