redis渐进式rehash

初步了解

Redis的渐进式rehash是指扩展或收缩哈希表时,需要将ht[0]里面的所有键值对rehash到ht[1]里面,但这个rehash动作并不是一次性、集中式地完成的,而是分多次、渐进式地完成的。这样做的原因在于,如果哈希表里保存的键值对数量很大时,如:四百万、四千万甚至更多,一次性、集中式地完成rehash动作,会导致服务器停止服务很长时间,影响用户体验。¹²

渐进式rehash的实现方式是:每次只对哈希表ht[0]里面的少量键值对进行rehash,并将它们逐个地迁移到ht[1]里面。在这个过程中,服务器仍然可以继续处理客户端发送过来的命令请求,并将新的键值对添加到ht[0]里面。当ht[0]里面所有键值对都被迁移到ht[1]里面之后,服务器就会使用ht[1]来代替ht[0],从而完成一次渐进式rehash动作。²

(1) Redis的渐进式rehash原理 - 知乎. https://zhuanlan.zhihu.com/p/358366217.
(2) 渐进式 rehash — Redis 设计与实现. http://redisbook.com/preview/dict/incremental_rehashing.html.
(3) Redis学习笔记篇一: 渐进式Rehash - 知乎. https://zhuanlan.zhihu.com/p/372566810.

渐进式rehash

Redis是当然如果这个数组一直不变,那么hash冲突会变很多,这个时候检索效率会大打折扣,所以Redis就需要把数组进行扩容(一般是扩大到原来的两倍),但是问题来了,扩容后每个hash桶的数据会分散到不同的位置,这里设计到元素的移动,必定会阻塞IO,所以这个ReHash过程会导致很多请求阻塞。

为了避免这个问题,Redis 采用了渐进式 rehash。

首先、Redis 默认使用了两个全局哈希表:哈希表 1 和哈希表 2。一开始,当你刚插入数据时,默认使用哈希表 1,此时的哈希表 2 并没有被分配空间。随着数据逐步增多,Redis 开始执行 rehash。

1、给哈希表 2 分配更大的空间,例如是当前哈希表 1 大小的两倍

2、把哈希表 1 中的数据重新映射并拷贝到哈希表 2 中

3、释放哈希表 1 的空间

在上面的第二步涉及大量的数据拷贝,如果一次性把哈希表 1 中的数据都迁移完,会造成 Redis 线程阻塞,无法服务其他请求。此时,Redis 就无法快速访问数据了。

image.png

在Redis 开始执行 rehash,Redis仍然正常处理客户端请求,但是要加入一个额外的处理:

处理第1个请求时,把哈希表 1中的第1个索引位置上的所有 entries 拷贝到哈希表 2 中

处理第2个请求时,把哈希表 1中的第2个索引位置上的所有 entries 拷贝到哈希表 2 中

如此循环,直到把所有的索引位置的数据都拷贝到哈希表 2 中。

这样就巧妙地把一次性大量拷贝的开销,分摊到了多次处理请求的过程中,避免了耗时操作,保证了数据的快速访问。

所以这里基本上也可以确保根据key找value的操作在O(1)左右。

猜你喜欢

转载自blog.csdn.net/a772304419/article/details/130567696