面试题答案
一键面试触发rehash操作的情况
- 哈希表的负载因子过高:当哈希表的负载因子(
load_factor = ht[0].used / ht[0].size
)达到一定阈值时,会触发rehash。在Redis中,这个阈值默认是1,当ht[0].used
大于等于ht[0].size
时,就满足了这个触发条件。 - 服务器执行
BGREWRITEAOF
或BGSAVE
命令:在这种情况下,为了避免fork出的子进程和父进程同时对哈希表进行rehash操作导致竞争问题,Redis会在后台进行lazy rehash
,也就是逐步进行rehash,而不是一次性完成。
对Redis数据结构的影响
- 哈希表扩展:触发rehash时,Redis会创建一个新的哈希表,新哈希表的大小通常是原哈希表大小的两倍(在负载因子过高触发时),这会改变哈希表的数据结构布局。例如,原哈希表中键值对在桶中的分布会因为新哈希表大小的改变而重新分布。
- 双哈希表结构:在
lazy rehash
过程中,Redis会同时使用两个哈希表(ht[0]
和ht[1]
),随着rehash的逐步进行,键值对会从ht[0]
迁移到ht[1]
,直到ht[0]
为空,此时ht[1]
成为新的主哈希表,ht[0]
被释放。
对性能的影响
- 一次性rehash:如果是因为负载因子过高而触发的常规rehash(非
lazy rehash
),在rehash过程中,Redis需要一次性将所有键值对重新计算哈希值并迁移到新的哈希表中,这会消耗大量的CPU时间,在这段时间内,Redis对外提供服务的性能会受到影响,响应时间可能变长。 - lazy rehash:在执行
BGREWRITEAOF
或BGSAVE
命令触发的lazy rehash
过程中,虽然避免了一次性rehash对性能的巨大冲击,但每次对哈希表进行操作(如读写)时,都会顺带迁移一部分键值对到新哈希表,这也会增加每次操作的耗时,不过这种影响相对较小,对Redis整体性能的影响较为平缓。