Redis数据结构——字典

1,字典,又称为符号表、关联数组、或映射,是一种用于保存键值对的抽象数据结构。
2,Redis的字典使用哈希表作为底层实现,哈希表的结构定义如下:

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

table属性是一个数组,数组中的每个元素都是一个指向dict.h/dictEntry结构的指针,每个dictEntry结构保存着一个键值对。sizemask的值和哈希值一起决定一个键应该被放到table数组的哪个索引上面。
3,哈希表节点结构:

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

4,字典结构:

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

其中,type属性和privdata属性是针对不同类型的键值对,为创建多态字典而设置的:
type属性是一个指向dictType结构的指针,每个dictType结构保存了一簇用户操作特定类型键值对的函数,Redis会为不同的字典设置不同的类型特定函数。
privdata属性则保存了需要传给那些类型特定函数的可选参数。 在这里插入图片描述ht属性是一个包含两个项的数组,数组中的每一项都是一个哈希表,但是通常字典只使用ht[0]哈希表,ht[1]哈希表只会在对ht[0]哈希表进行rehash时使用。
rehashidx记录的是rehash的进度,当前没有rehash值是-1
5,要将一个新的键值对添加到字典里面时,需要做两步:
1)使用字典设置的哈希函数,计算键key的哈希值。
2)使用哈希表的sizemask属性和哈希值,计算出索引值。
随着操作的不断进行,哈希表保存的键值对会逐渐的增多或者减少,为了让哈希表的负载因子维持在一个合理的范围内,当哈希表保存的键值对数量太多或者太少时就需要进行rehash。主要通过如下3步:
1)为字典的ht[1]哈希表分配空间,这个哈希表的空间大小取决于要执行的操作,以及ht[0]当前包含的键值对数量:
如果执行扩展操作,那么ht[1]的大小为第一个大于等于ht[0].used*2的2的n次幂。
如果是收缩操作,那么ht[1]的大小是第一个大于等于ht[0].used的2的n次幂。
2)将保存在ht[0]中的所有键值对rehash到ht[1]。
3)将ht[0]包含的所有键值对迁移到ht[1]之后,释放ht[0],将ht[1]设置为ht[0],并在ht[1]新创建一个空白哈希表,为下一次rehash做准备。
6,需要注意的是,执行上面rehash的时候,系统应该是渐进式的,而不应该是集中式的。因为,如果哈希表里保存的键值对不是4个而是几亿个,一次性rehash可能会导致服务器在一段时间暂停服务任务。渐进式rehash的步骤如下:
1)为ht[1]分配空间,让字典同时持有ht[0]和ht[1]两个哈希表
2)在字典中维持一个索引计数器变量rehashidx,并将它的值设置为0,表示rehash工作开始
3)在rehash期间,每次对字典执行添加、删除、查找或者更新操作时,程序除了执行指定的操作外,还会顺带将ht[0]哈希表在rehashidx索引上的所有键值对rehash到ht[1],这时程序将rehashidx属性的值增1
4)随着字典操作的不断执行,最终在某个时间点上,ht[0]的所有键值对都会被rehash至ht[1],这时将rehashidx的值设置为-1,表示rehash操作已经完成。
7,渐进式rehash过程中,字典会同时使用ht[0],和ht[1]两个哈希表,所以在渐进式rehash进行期间,字典的删除、查找、等操作会在两个哈希表上进行。
在渐进式rehash执行期间,新添加到字典的键值对一律会被保存到ht[1]里面。

猜你喜欢

转载自blog.csdn.net/xiaoan08133192/article/details/115094802