面试题答案
一键面试哈希表扩容条件
- 负载因子过高:负载因子 = 哈希表已保存节点数量 / 哈希表大小。当负载因子大于等于1,并且Redis没有在执行BGSAVE命令或者BGREWRITEAOF命令(也就是没有后台I/O操作在进行)时,会触发扩容。
- 当执行BGREWRITEAOF命令或者BGSAVE命令时:如果负载因子大于等于5,也会触发扩容。
代码层面扩容操作
- 数据结构调整:
- 分配新的哈希表空间。新哈希表的大小是原哈希表大小的2倍,并且是大于等于原大小2倍的第一个2的幂次方数。例如原哈希表大小为4,新哈希表大小为8。
- 原哈希表ht[0] 不变,新哈希表ht[1] 被分配空间。
- 在扩容过程中,字典的rehashidx字段会从 -1变为0,表示开始进行rehash操作。
- 函数调用:
dictExpand
函数负责分配新的哈希表空间,并初始化相关参数。它会根据当前哈希表已保存节点数量,计算出合适的新哈希表大小并分配内存。dictRehash
函数负责逐步将原哈希表中的键值对迁移到新哈希表。在进行实际迁移时,每次迁移一个桶(bucket)中的所有节点。该函数会循环从ht[0] 中取出一个桶,将桶中的所有节点重新计算哈希值并插入到ht[1] 中合适的位置,然后将rehashidx加1,指向下一个要迁移的桶。迁移完成后,将ht[0] 释放,ht[1] 成为新的ht[0],并将rehashidx重新设为 -1,表示rehash操作完成。