数据库
首页 > 数据库> > [ Redis14篇]字典之渐进式Hash结构

[ Redis14篇]字典之渐进式Hash结构

作者:互联网

1.Redis字典Hash底层数据结构?

Redis 字典 hash 的数据结构底层是一个 dict 对象。

dict的结构:

2.如何计算的Hash 值

Redis 使用** MurmurHash2 算法**来计算键的哈希值。
MurmurHash 算法最初由 Austin Appleby 于 2008 年发明, 这种算法的优点在于, 即使输入的键是有规律的, 算法仍能给出一个很好的随机分布性, 并且算法的计算速度也非常快。

3.如何解决哈希冲突

答:数组+链表
插入一条新的数据时,会进行哈希值的计算,如果出现了hash值相同的情况,
Redis 中采用了连地址法(separate chaining)来解决键冲突。每个哈希表节点都有一个next 指针,多个哈希表节点可以使用next 构成一个单向链表,被分配到同一个索引上的多个节点可以使用这个单向链表连接起来解决hash值冲突的问题。

这里使用的是头插法,因为哈希表节点中没有记录链表尾节点位置(复杂度为 O(1))

4.什么是渐进式扩容(Rehash)

渐进式rehash指的是,redis hash 结构维护了2个表,一个是旧表,一个是新表大小是旧表的2倍。
当需要扩容的时候,并不是一次性操作全量数据,而是分散在了 读、写、删 的操作中,逐步迁移,直到迁移完成。
ps: 读/删:先去ht[0]找,找不到去ht[1]。 2)写:直接写在ht[1]

Redis既然采用的是 渐进式rehash为了提高性能,若每次rehash都操作全量数据,是非常耗性能的

总结:分而治之,避免了集中式rehash 带来的庞大计算量。

5.什么时候进行扩容(Rehash)?

在redis中,字典里的哈希会根据以下两种情况进行扩容:

其中哈希表的负载因子可以通过公式:

6.为什么扩容因为是否在持久化的负载因子不同

因为在执行 bgsave 命令或者bgrewriteaofF 命令的过程中
Redis 需要创建当前服务器进程的子进程,而大多数操作系统都采用写时复制 (copy-on-write)技术来优化子进程的使用效率,所以在子进程存在期间,服务器会提高执行扩展操作所需的负载因子,尽可能地避免在子进程存在期间进行哈希表扩展操作。这可以避免不必要的内存写入操作,最大限度节约内存。
另一方面,当哈希表的负载因子小于0.1时,程序自动开始对哈希表执行收缩操作。

7.Redis Rehash机制优化

在Redis满容驱逐状态下,如何避免因Rehash而导致Redis抖动的这种问题呢?

8.Rehash的过程中有数据变化怎么办

保证redis在h[0]上是只少不多,所有的记录逐步被迁移到h[1]

9.Redis单线程渐进式如何Rehash(扩容)

Rehash操作分为两种
扩展:当负载因子较大时,应该扩大 dictht::size 以降低平均长度,加快查询速度 。
收缩:当负载因子较小<0.1时,应该减小 dictht::size 以减少对内存的浪费 。

采用渐进式rehash 的好处在于它采取分而治之的方式,避免了集中式rehash 带来的庞大计算量
渐进式rehash 的详细步骤:

标签:rehash,Hash,Rehash,Redis,Redis14,ht,渐进式,哈希
来源: https://blog.csdn.net/qq_38011415/article/details/121736340