面试题答案
一键面试Redis字典rehash触发条件
- 负载因子过高:当哈希表的负载因子(load factor)大于等于1时,且服务器没有在执行BGSAVE命令或者BGREWRITEAOF命令,此时会触发rehash。负载因子的计算公式为:
负载因子 = 哈希表已保存节点数量 / 哈希表大小
。 - 执行BGSAVE或BGREWRITEAOF命令期间:如果在执行这两个命令期间,负载因子大于等于5,也会触发rehash。这是因为在执行这两个后台持久化命令时,Redis需要尽量减少内存的使用,避免内存压力过大。
Redis利用时间片机制逐步完成rehash过程及性能优化
- rehash步骤
- 分配新哈希表:为字典的ht[1]分配空间,其大小一般是当前ht[0]大小的两倍(如果ht[0]为空,ht[1]的大小会被初始化为4)。
- 渐进式rehash:在触发rehash后,Redis不会立即将ht[0]中的所有键值对一次性迁移到ht[1]中,而是采用渐进式rehash。即每次执行哈希表相关的操作(如添加、删除、查找、更新)时,除了执行原有的操作之外,还会在ht[0]中随机选取一些键值对,将它们迁移到ht[1]中。
- 指针切换:当ht[0]中的所有键值对都迁移到ht[1]后,释放ht[0],将ht[1]设置为ht[0],并为ht[1]重新分配一个空的哈希表,等待下一次rehash。
- 时间片机制与性能优化
- 结合操作进行迁移:通过在每次哈希表相关操作时顺带迁移部分键值对,利用了操作执行的时间片,避免了专门为rehash分配大量连续时间,从而减少对系统性能的影响。例如,在处理客户端的命令请求时,处理命令本身需要一定时间,在这个时间片内,顺带执行少量的rehash操作,不会让客户端感觉到明显的延迟。
- 减少单次迁移量:每次只迁移少量键值对,避免一次性大量数据迁移导致的CPU和内存占用过高。这样可以保证系统在rehash过程中仍然能够正常处理其他请求,维持系统的高可用性和响应性能。例如,每次迁移10个键值对,相比于一次性迁移1000个键值对,对系统性能的冲击要小得多。