[Redis] 哈希表的Rehash機制


哈希表的完整結構 , 因為他是多個哈希一層層嵌套的 , 所以會是這樣的結構

 

 

 

觸發rehash的時機

字典類型容量變化過程叫做rehash,需要滿足一定的條件才能觸發擴容機制
服務器當前沒有進行BGWRITEAOF或者BGSAVE命令,且當前鍵值對個數超過一維數組的大小,才會觸發擴容。

如果當前鍵值對個數超過一維數組大小的五倍,無論是否在進行BGWRITEAOF或者BGSAVE命令,都會強制擴容。
Hash類型擴容后數組的長度為原來的二倍


縮容機制:如果當前鍵值對個數少於一維數組大小的十分之一,則觸發縮容過程。縮容不會考慮當前服務器是否在進行BGWRITEAOF或者BGSAVE命令

 

漸進式rehash的過程

利用了兩個哈希表進行的 , 有點類似數據庫的遷移 , 讀的時候先讀舊庫 , 讀不到讀新庫 , 寫的時候只寫新庫 ; 其他舊數據一點點的往新庫上搬

 

當觸發擴容的時候,Redis會首先為ht[1] 分配一塊內存空間。如果當前字典是一個比較大的字典,那么整個擴容過程的時間復雜度為O(n),直接完整進行擴容機制可能會導致Redis一段時間內停止服務。為了避免停止服務的情況,Redis的設計團隊采用了漸進式rehash的策略,每次只對原哈希表中的一小部分進行搬遷,這樣漸進式的進行,直到全部鍵值對都遷移到新的哈希表中。

 

首先,對於key的查詢,我們需要到原來的哈希表中進行查找,如果找到對應的value,直接返回就可以了。如果沒有找到,那么只有兩種可能,一個是這個鍵值對已經搬遷到新的哈希表了,另外一種可能是根本就不存在這個鍵值對,無論是哪種可能,我們都需要再去新哈希表中對他進行查找,如果找到了就返回,如果找不到說明這個鍵值對不存在。

 

步驟如下:
1.為字典的備用哈希表分配空間:
如果執行的是擴展操作,那么備用哈希表的大小為第一個大於等於(已用節點個數)*2的2n(2的n次方冪)
如果執行的是收縮操作,那么備用哈希表的大小為第一個大於等於(已用節點個數)的2n
2.在字典中維持一個索引計數器變量rehashidx,並將它的值設置為0,表示rehash工作正式開始(為-1時表示沒有進行rehash)。
3.rehash進行期間,每次對字典執行添加、刪除、查找或者更新操作時,程序除了執行指定的操作以外,還會順帶將ht[0]哈希表在rehashidx索引上的所有鍵值對rehash到ht[1],當一次rehash工作完成之后,程序將rehashidx屬性的值+1。同時在serverCron中調用rehash相關函數,在1ms的時間內,進行rehash處理,每次僅處理少量的轉移任務(100個元素)。
隨着字典操作的不斷執行,最終在某個時間點上,ht[0]的所有鍵值對都會被rehash至ht[1],這時程序將rehashidx屬性的值設為-1,表示rehash操作已完成。

初始化ht[1]  0-7 ,  ht[0]是舊的有數據  0-3

 

開始搬遷 , 把就ht[0] 0上的數據 , 搬到了新的ht[1] 的4的部分

 

 

 rehash完成 , 把ht[0]上的全都搬到ht[1]上了

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM