Redis_dict 字典

1.总结:

1. 字典被用于实现redis的功能包括数据库和哈希键
2.Redis 字典的底层实现采用哈希表,每个字典采用两个哈希表 一个平时用,一个在rehash的时候用
3. Redis使用MurmurHash2的算法来进行hash计算
4. Redis对于产生了hash冲突的键采用链地址法结局hash冲突,并且是头插法形成一个单向链表
5.在对hash表进行扩展和收缩的时候 需要采用渐进式hash的方法进行扩展或收缩

2. 分解

2.1 字典的数据结构 (dict.h/dict)

typedef struct
{
	dictType *type;// 类型特定的函数
	void * privatedata; //私有数据
	dictht *[2];//哈希表
	int trehashidx;//索引值在rehash的时候作为标记使用
}

//dictType的数据结构
typedef struct{
unsigned int(*hashfunction)(const void*key);//计算hash值的函数
void*(*keyDup)(void*privatedata, void*key);//复制键的函数
.
.
.
}

2.2 hash 表的数据结构 (dict.h/dictht)

typedef struct dictht
{
	dictEntry **table; //hash表数组 存储hash之后的键值对
	unsigned long size;//哈希表的大小
	unsigned long sizemask;//哈希表的掩码,用于与hash函数计算hash的键
	unsigned long used;//已经使用的节点数量
}

//hash表数据节点的结构提
typedef struct dictEntry{
void *key;//数据的键
union{
	void *val;
	uint64_t u64;
	int64_t i64
};//联合的结构体存储不同的数据
struct dictEntry*next;//指向下一个节点 用于解决hash冲突
}

2.3 整体结构图

dict

3.知识要点

3.1 如何解决hash冲突

redis是使用的MurmurHash2算法来计算hash值的 当需要在字典里面插入一个值的时候 调 dict->type->hashFunction(key) 来计算得到一个hash值,然后用得到的hash值与dict->ht[x].sizemask进行&操作 得到具体需要插入的索引值,如果由多个键得到的hash结果是一样的,那么在产生hash冲突的时候,redis采用的是链地址法来进行处理 也就是用dictEntry->next 来保存这个产生的hash 冲突的键值对 并且是插入到前面,之所以插入到前面是一般新创建的键 使用的频率比较高 这样方便查找

hash冲突

3.2 渐进式rehash(hash的扩容和收缩操作)

  • 1.为ht[1]分配空间 分配空间的规则是 如果是扩容操作就是第一个2^n的值大于等于ht[0]已经使用空间的两倍 即 2^n >= ht[0].used*2 如果是收缩操作就是第一个2^n的值大于等于ht[0]已经使用空间 即2^n >= ht[0].used
  • 2.在字典ht[0]中维持一个索引计数器rehashidx 并在开始的时候将它置为0,表示rehash正式的开始工作
    1. 在rehash 期间程序的添加,删除 查找和更新的操作,程序除了执行指定的操作 还将ht[0]中rehashidx所指向的键值对rehash到ht[1],完成之后rehashidx的值加1 ps 在rehash的过程中 所有新添加的键一律都放入到ht[1]中 这样就可以保证ht[0]中的数据 只减少不增加
  • 4.在将ht[0]中的所有数据都rehash到ht[1]的时候 将ht[1]修改为ht[0]并且将rehashidx置为-1
    **采用渐进式rehash的方法 可以有效的避免数据区扩展或收缩的时候 统一处理所带来庞大的计算量,采用分而治之的思想 **

3.3 字典的api

  • dictcreate 创建一个新的字典
  • dictadd 添加一个新的键值对
  • dictReplace 将给定的键值对添加到字典里面 如果已经存在就直接替换
  • dictFetchValue 返回给定键的值
  • dictGetRandomKey 从字典中随机返回一个键值对
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值