在扩容和收缩的时候,如果哈希字典中有很多元素,一次性将这些键全部rehash到ht[1]
的话,可能会导致服务器在一段时间内停止服务。所以,采用渐进式rehash的方式,详细步骤如下:
- 为
ht[1]
分配空间,让字典同时持有ht[0]
和ht[1]
两个哈希表 - 将
rehashindex
的值设置为0
,表示rehash工作正式开始 - 在rehash期间,每次对字典执行增删改查操作是,程序除了执行指定的操作以外,还会顺带将
ht[0]
哈希表在rehashindex
索引上的所有键值对rehash到ht[1]
,当rehash工作完成以后,rehashindex
的值+1
- 随着字典操作的不断执行,最终会在某一时间段上
ht[0]
的所有键值对都会被rehash到ht[1]
,这时将rehashindex
的值设置为-1
,表示rehash操作结束
渐进式rehash采用的是一种分而治之的方式,将rehash的操作分摊在每一个的访问中,避免集中式rehash而带来的庞大计算量。
需要注意的是在渐进式rehash的过程,如果有增删改查操作时,如果index
大于rehashindex
,访问ht[0]
,否则访问ht[1]
总结:redis的rehash目的就是redis的扩容时,重新对数据进行hash,也就是原先的hash表 ht[0] (hashtable[0]) 的key进行重新hash,再存到一个全新的hash表中,若要一次性将这些键全部rehash到ht[1]
(hashtable[1].扩容后的哈希表)的话,会导致服务器在一段时间内停止服务(必须全部rehash过程完成),所以,采用渐进式rehash的方式
渐进式rehash:
- 为
ht[1]
分配空间,让字典同时持有ht[0]
和ht[1]
两个哈希表 - 将
rehashindex
的值设置为0
,表示rehash工作正式开始 - 在rehash期间,每次对字典执行增删改查操作是,程序除了执行指定的操作以外,还会顺带将
ht[0]
哈希表在rehashindex
索引上的所有键值对rehash到ht[1]
,当rehash工作完成以后,rehashindex
的值+1
- 随着字典操作的不断执行,最终会在某一时间段上
ht[0]
的所有键值对都会被rehash到ht[1]
,这时将rehashindex
的值设置为-1
,表示rehash操作结束
渐进式rehash采用的是一种分而治之的方式,将rehash的操作分摊在每一个的访问中,避免集中式rehash而带来的庞大计算量。
需要注意的是在渐进式rehash的过程,如果有增删改查操作时,如果index
大于rehashindex
,访问ht[0]
,否则访问ht[1]
(1)上面说了,rehash的时候rehashindex
的值设置为0,
表示rehash工作正式开始,
(2)当rehash工作完成以后,rehashindex
的值+1
, rehashindex >0; 就是说 一个index 一个index的进行key的迁移,每迁移一个index就 rehashindex + 1
所以rehashindex就是已经index< rehashindex的下标对应的链表已经迁移过了,迁移到 ht[1] 上,index > rehashindex 还没迁移,index = rehashindex正在迁移
(3)ht[0]
的所有键值对都会被rehash到ht[1]
,这时将rehashindex
的值设置为-1
,表示rehash操作结束
有增删改查操作时,如果index
大于rehashindex
就是还没迁移的index,就访问ht[0](原始的hashtable), 否则就是 已经迁移过的和正在迁移的,都操作新的 ht[1],
更多精彩分享请移步:IT学习道场
更多分享关注公众号【IT学习道场】