redis set类型数据结构字典之rehash

1,273 阅读2分钟

小知识,大挑战!本文正在参与「程序员必备小知识」创作活动

7redis set类型数据结构字典之rehash

什么时候进行哈希表的扩展操作呢?

  1. 服务器目前没有在执行BGSAVE命令或者BGREWRITEAOF命令,并且哈希表的负载因子大于等于1
  2. 服务器目前正在执行BGSAVE命令或者BGREWRITEAOF命令,并且哈希表的负载因子大于等于5

负载因子怎么算的呢?

负载因子=ht[0].used/ht[0].size,也就是哈希表已保存节点数量与哈希表的大小相除

为什么根据BGSAVE命令或者BGREWRITEAOF命令是否执行,负载因子还不相同呢?

这是因为在执行BGSAVE命令或者BGREWRITEAOF命令过程中,redis需要创建当前服务器进程的子进程,子进程存在期间,服务器会提高负载因子,避免子进程存在期间进行哈希扩展操作,避免不必要的内存写入操作,最大限度节约内存。

什么时候进行哈希表的收缩操作呢?

当哈希表的负载因子小于0.1的时候进行收缩。

渐进式rehash

为什么要使用渐进式rehash

如果哈希表里保存的键值对很多,要一次性将这些键值对全部rehash到ht[1],庞大的计算量导致服务器在一段时间内停止服务,为了避免rehash对服务性能造成影响,服务器不是一次性全部rehash,而是分多次、渐进式的将ht[0]里面的键值对慢慢rehash到ht[1]

渐进式rehash的步骤:

渐进式rehash的步骤:

  1. 为ht[1]分配空间,让字典同时持有ht[0]和ht[1]两个哈希表
  2. 在字典中维持一个索引计数器变量rehashidx,并将它的值设置为0,表示rehash工作正式开始
  3. 在rehash进行期间,每次对字典执行添加、删除、查找或更新操作,程序除了执行指定的操作以外,还会顺带将ht[0]哈希表在rehashidx索引上的所有键值对rehash到ht[1],当rehash工作完成后,rehashidx属性增1
  4. 随着字典操作的不断执行,最终ht[0]的所有键值对都会被rehash到ht[1],这事程序将rehashidx属性值设置为-1,表示rehash操作完成

渐进式rehash进行期间,字典的删除、查找、更新等操作会在两个哈希表上进行。

渐进式rehash执行期间,新添加到字典的键值对会被保存到ht[1]里面,ht[0]不再进行任何添加操作,保证了ht[0]包含的键值对数量只减不增,随着rehash操作的执行最终变成空表。