链表和字典

1.链表
链表提供了强大重排能力和顺序访问方式。列表键的底层实现就是链表。比如一个列表键包含了1到1024的整数。

链表节点是一个具有值,指向前一个元素的指针,指向后一个元素的指针。所以这是一个双向链表。且链表中含有复制判断是否相等长度等函数。方便我们使用。

2.字典
Redis数据库底层实现就是字典。此外,哈希键的实现也是字典。

2.1哈希表
字典是以哈希表作为底层实现的。由一个结构体定义:
在这里插入图片描述
其中,table是一个数组,数组元素是指向一个字典结构的指针,每个字典结构保存一个键值对,哈希表大小掩码和哈希值一起决定一个键放到table的哪个位置上。

2.2哈希表节点
哈希表节点使用字典结构表示,每个节点表示一个键值对
在这里插入图片描述
next用于指向另一个哈希表节点,用来解决哈希冲突,和拉链法类似。

2.3字典
在这里插入图片描述
其中type,private属性是为了针对不同类型的键值对,创建多态字典设置的。
而ht[2]是一个两项的数组,每一项都是一个dictht哈希表,一般我们只使用ht[0]哈希表,第二个哈希表是为了rehash设置的,而rehashidx记录了rehash的进度,没有rehash时值为-1;

在这里插入图片描述
2.4 哈希算法
当一个新的键值对添加到字典时,程序首先要根据键来计算哈希值和索引值,然后把它放到对应的哈希表节点位置。计算方法如图:
在这里插入图片描述
在Redis中,哈希值计算一般用murmurhash法,这个算法的优点在于即使输入是非常规律的,计算出结果也具有随机分布性,且计算速度快。

2.5 rehash
随着操作进行,哈希表保存的键值对会不断增加或减少,为了让哈希表的负载因子维持在合理范围内,当哈希表键值对过多或过少时,我们需要对哈希表大小进行相应扩展和收缩。这就是rehash操作。
步骤:1、为字典的ht[1]哈希表分配空间。如果是扩展操作,空间大小为第一个大于等于ht[0].used*2的2的n次方幂;如果是收缩操作,大小为第一个大于等于ht[0].used的2的n次方幂;
2、重新计算ht[0]中键值对的哈希值索引值,移动到ht[1]中;
3、释放ht[0],将ht[1]设置为ht[0],并创建一个空白哈希表ht[1],为下一次rehash做准备。
而负载因子就是使用节点数/哈希表大小。一般小于0.1就要收缩,大于1扩展,特殊命令时除外。这里不仔细说了。

2.6渐进式rehash
渐进式指的就是将数据从ht[0]到ht[1]不是一次性完成,而是多次完成。原因很简单,如果ht[0]保存了千万甚至上亿级别的键值对,一次完成需要花费一段时间,这段时间服务器会停止服务,对服务器性能造成影响。这点和动态存储器的集中刷新方式有点像,集中刷新会导致死区时间过长。

渐近rehash期间,由于同时存在两个哈希表,查找时会首先查找0,再查找1,添加新元素时只会插入到1中,保证0最终会空。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值