Redis的字典实现

字典概念

键值对:键和值进行关联,这些关联的键和值就是键值对
字典:又称符号表、关联数组、映射,是一种用于保存键值对的抽象数据结构

哈希表节点定义

typedef struct dictEntry {
	void *key;//键
	union{
		void *val;
		uint64 _tu64;
		int64 _ts64;
	}v;//值
	struct dictEntry *next;//指向下个哈希表节点,形成链表,将多个哈希值相同的键值对连接在一起,用于解决键冲突问题
}dictEntry;

哈希表定义

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

字典定义

//类型特定函数定义
typedef struct dictType{
	unsigned int (*hashFunction)(const void *key);//计算哈希值函数(如 MurmurHash算法)
	void *(*keyDup)(void *privdata, const void *key);//复制键函数
	void *(*valDup)(void *privdata, const void  *obj);//复制值函数
	void *(*keyCompare)(void *privdata, const void *key1, const void *key1);//对比键函数
	void (*keyDestructor)(void *privdata, void *key);//销毁键函数
	void (*valDestructor)(void *privdata, void *obj);//销毁值函数
}dictType;

//字典定义
typedef struct dict{
	dictType *type;//类型特定函数,为用途不同字典设置不同的类型特定函数
	void *privdata;//私有数据,传给那些类型特定函数的可选参数
	dictht ht[2];//哈希表 ht[1]用于rehash
	int trehashidx;//rehash索引,记录哈希进度,-1 未进行rehash中
}dict;

rehash(重新散列)

为了让哈希表的负载因子维持在一个合理的范围内,当哈希表保存的键值对数量大多或者太少时,需要对哈希表的大小进行相应的扩展或收缩。

Redis对字典的哈希表执行rehash的步骤:
1、为字典ht[1]哈希表分配空间,这个哈希表的空间大小取决于要执行的操作以及ht[0]当前包含的键值对数量(ht[0].used),如果执行的是扩展操作,那么ht[1]的大小为第一个大于等于ht[0].used*2的n次幂,如果执行的是收缩操作,那么ht[1]的大小为第一个大于等于ht[0].used的2的n次幂。

2、将保存在ht[0]中的所有键值对rehash到ht[1]上面rehash指的是重新计算键的哈希值和索引值,然后将键值对放置到ht[1]哈希表的指定位置上。

3、当ht[0]包含的所有键值对都迁移到了ht[1]之后释放ht[0]将ht[1]设置为ht[0],并在ht[1]新创键一个空白哈希表为下一次rehash做准备。

负载因子计算公式:负载因子 = 哈希表节点数量 / 哈希表大小

哈希表的扩展操作:
1、服务器目前没有在执行bgsave命令或者bgrewriteaof命令,并且哈希表的负载因子大于等于1;
2、服务器目前正在执行bgsave命令或者bgrewriteaof命令并且哈希表的负载因子大于等于5;

哈希表的收缩操作:哈希表负载因子小于0.1

哈希表渐进式rehash采用分而置之的方式,避免了集中式rehash带来的庞大计算量,在进行期间,字典的删除、查找、更新等操作会在两个哈希表上进行,新添加到字典的键值对一律会保存到ht[1]里面,则ht[0]不再进行任何添加操作。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值