面试题答案
一键面试触发 rehash 的条件
- 负载因子过高:Redis 会计算哈希表的负载因子,公式为:
负载因子 = 哈希表已保存节点数量 / 哈希表大小
。当负载因子大于等于 1 且redis.hz
(服务器每秒执行的频率)的值大于 10 时,会触发 rehash。此外,当负载因子大于等于 5 时,无论redis.hz
的值是多少,都会强制触发 rehash。这是为了避免哈希表过于拥挤,导致操作性能下降。 - 哈希表收缩:当哈希表的负载因子小于 0.1 时,会触发哈希表的收缩操作,即进行 rehash 来减少哈希表的大小,以节省内存。
数据迁移过程
- 分配新哈希表:Redis 为新哈希表分配内存空间,新哈希表的大小一般是旧哈希表大小的两倍(扩张时)或者是根据负载因子计算出合适的较小值(收缩时)。
- 渐进式 rehash:Redis 采用渐进式 rehash 方式,而不是一次性将所有数据从旧哈希表迁移到新哈希表。这是因为一次性迁移可能会导致服务器在迁移过程中长时间无法处理其他请求。在 rehash 期间,Redis 会同时保留新旧两个哈希表。
- 逐步迁移:在每次执行命令时(例如处理客户端的读、写等操作),Redis 会在适当的时候从旧哈希表中取出一小部分数据迁移到新哈希表。具体来说,每次会迁移
rehashidx
索引位置及其之后的部分数据(rehashidx
记录了当前迁移到旧哈希表的哪个索引位置)。迁移完成后,rehashidx
会指向下一个需要迁移的位置。 - 最终完成:当旧哈希表中的所有数据都迁移到新哈希表后,释放旧哈希表的内存,并将新哈希表设置为当前使用的哈希表,
rehashidx
重置为 -1,表示 rehash 操作完成。