建议先关注、点赞、收藏后再阅读。
在Redis中,rehash是指当哈希表的负载因子(load factor)超过设定阈值时,为了保证哈希表的性能,系统会自动触发rehash操作。Rehash操作指的是将原来的哈希表重新建立一个更大的哈希表,并将原有的键值对重新映射到新的哈希表上。
发生rehash操作的主要原因是为了保持哈希表的负载因子在一个合理范围内,以提高哈希表的性能。当哈希表的负载因子过高时,查询和插入键值对的效率会降低,因为哈希冲突的概率增加,需要更多的线性查找时间来定位到正确的槽位。
为了避免负载因子过高的情况发生,当哈希表的负载因子超过设定阈值时,Redis会自动触发rehash操作,将原有的哈希表进行扩容,并重新映射键值对到新的哈希表上。
以下是rehash的过程:
Redis首先为新哈希表申请更大的内存空间,并初始化新哈希表的槽位数为当前槽位数的两倍。
Redis将新哈希表的引用保存到字典的"ht[1]"属性中,并将字典的rehashidx属性设置为0,表示rehash操作正在进行中。
每次执行命令时,Redis在执行之前都会先检查rehash操作是否进行中。如果进行中,Redis会继续进行rehash操作的下一步。
Redis每次从旧哈希表中取出一个槽位并遍历该槽位中的所有键值对。
对于每一个键值对,Redis会计算键的哈希值,并根据新哈希表的槽位数取模,确定新哈希表中的对应槽位。
Redis将该键值对从旧哈希表的槽位中删除,并将其插入到新哈希表的对应槽位中。
重复步骤4~6,直到旧哈希表的所有槽位都被遍历完成。
当旧哈希表的所有槽位都迁移完成时,Redis会将新哈希表的引用保存到字典的"ht[0]"属性中,并将rehashidx属性设置为-1,表示rehash操作完成。
此时,Redis会在执行命令前检查rehash操作是否完成。如果完成,Redis会直接使用新哈希表进行操作。
通过逐步迁移键值对的方式,Redis能够平滑地进行rehash操作,避免在操作中断期间对系统的影响。在迁移过程中,旧哈希表和新哈希表共同存在,但所有的操作都会基于新哈希表进行。一旦迁移完成,系统会切换到新哈希表上,并释放旧哈希表的内存空间。
渐进式rehash在Redis字典中的作用是将旧的哈希表慢慢迁移到新的哈希表中,以实现字典的动态扩容。这样可以对数据库进行更快速的操作。
具体的过程如下:
Redis会为新哈希表分配更大的空间,并将新哈希表的指针保存在字典的rehash属性中。
每当执行一个读写操作时,Redis只需要同时访问两个哈希表中的键值对,即旧哈希表和新哈希表。
在rehash过程中,Redis会每次从旧哈希表中迁移一些键值对到新哈希表中,并更新rehash属性中的进度指示器,指示已经完成了多少百分比的迁移操作。
通过分批迁移的方式,Redis可以避免一次性地将所有键值对都迁移,从而减少了rehash操作对数据库的瞬时阻塞。
通过渐进式rehash的方式,Redis能够在不影响对数据库的读写操作的同时,逐步将旧的哈希表中的键值对迁移到新的哈希表中,实现了平滑的字典扩容。