ICode9

精准搜索请尝试: 精确搜索
首页 > 数据库> 文章详细

Redis字典

2021-05-11 22:30:03  阅读:150  来源: 互联网

标签:rehash Redis ht 键值 哈希 字典


Redis字典

一种用于保存键值对的抽象数据结构,Redis的数据库就是使用字典来作为底层实现的,字典还是哈希键的底层实现之一.

字典的实现

Redis中字典使用哈dictht表作为底层,一个哈希表里面可以有多个哈希表结点,而每个哈希表结点就保存了字典中的一个键值对.

哈希表

typedef struct dictht{
	//哈希表数据
	dictEntry **table;
	//哈希表大小
	unsigned long size;
	//哈希表大小掩码,用于计算索引值
	//总是等于size - 1
	unsigned long sizemask;
	//该哈希表已有结点数量
	unsigned long used;
}dictht;

table是一个数组,数组中每一个元素指向dictEntry结构的指针

size是哈希表的大小也就是数组的大小

used是哈希表中键值对的数量

sizemask用来确定一个键应该被放到table数组的哪一个索引里面

哈希表结点

typedef struct dictEntry{
	//键
	void *key;
	//值
	union{
		void *val;
		uint64_t u64;
		int64_t s64;
	}v;
	//指向下一个哈希表结点,形成链表
	struct dictEntry *next;
}dictEntry;

key保存键 v 保存值 next是使用链地址法来解决哈希冲突

字典

typedef struct dict{
	//类型特定函数
	dictType *type;
	//私有属性
	void *privdata;
	//哈希表
	dictht ht[2];
	//rehash 索引
	//当rehash不在进行时值为-1
	int rehashidx;
}dict;

ht属性

是一个包含两个项的数组,数组中每个项都是一个哈希表,ht[1]会在rehash时候使用,正常情况下只使用ht[0].

rehashidx

它记录了rehash目前的进度,如果目前没有在进行rehash,那么他的值为-1。

哈希算法

使用字典设置的哈希函数计算键key的哈希值

hash = dict->type->hashFunction(key);

使用哈希表的sizemsk属性和哈希值计算出索引值

index = hash & dict->ht[x].sizemask;

计算到索引之后表示此k-v键值对应该被放到哈希表对应索引中

解决键冲突

Redis使用链地址法来解决键冲突

特点:因为dictEntry结点组成的链表没有指向链表表尾的指针,也就是没有像Redis链表一样的指向头和尾的指针,所以为了速度考虑,当出现哈希冲突时Redis总是使用头插法,将新结点插到最前面。

rehash(重新散列)

为了让哈希表的负载因子维持在一个合理的范围之内,程序会对哈希表进行扩展或者收缩。可以通过rehash完成。

rehash步骤

1.为ht[1]分配空间

​ 扩展操作:ht[1]的大小为2^n (2^n >= ht[0].used*2 )n取最小值 键值对数量的二倍

​ 收缩操作: ht[1]的大小为2^n (2^n >= ht[0].used)n取最小值 键值对数量

2.将ht[0]中的所有键值对执行rehash到ht[1] 重新计算哈希值与索引
3.迁移完毕后,释放ht[0] 将ht[1]设置为ht[0] 并在ht[1]创建一个空的哈希表

渐进式rehash

这个动作分多次的渐进式的完成

1.为ht[1]分配空间,让字典同时存在两个哈希表ht[0]和ht[1]
2.字典dict中的rehashidx(索引计数器)将其设置为0,表示rehash开始
3.在rehash期间对字典执行添加、删除、查找、或者更新操作程序除了执行操作还会顺带将ht[0]在rehashidx索引上的所有键值对rehash到ht[1],当rehash工作结束后rehashidx+1
4.当ht[0]上的所有键值都被rehash到ht[1]上时,将rehashidx设置为-1,表示rehash操作完成。

渐进式rehash的好处在于它采取分而治之的方式,将rehash的操作分解到对字典的增删改查上,避免了集中式rehash带来的大计算量

渐进式rehash执行期间的哈希表操作

再次过程中字典会同时使用ht[0]和ht[1]两个哈希表,字典的个助攻操作都会在两个哈希表上进行,eg查找一个键会先查找ht[0]然后查找ht[1],另外在rehash执行期间,新添加的键值对会被保存到ht[1]里面,而ht[0]不会在进行添加操作。

标签:rehash,Redis,ht,键值,哈希,字典
来源: https://blog.csdn.net/qq_45462711/article/details/116672958

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有