[Redis] 哈希表的Rehash機制

哈希表的完整結構 , 由於他是多個哈希一層層嵌套的 , 因此會是這樣的結構數據庫

 

 

 

觸發rehash的時機數組

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

若是當前鍵值對個數超過一維數組大小的五倍,不管是否在進行BGWRITEAOF或者BGSAVE命令,都會強制擴容。
Hash類型擴容後數組的長度爲原來的二倍函數


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

 

漸進式rehash的過程設計

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

 

當觸發擴容的時候,Redis會首先爲ht[1] 分配一塊內存空間。若是當前字典是一個比較大的字典,那麼整個擴容過程的時間複雜度爲O(n),直接完整進行擴容機制可能會致使Redis一段時間內中止服務。爲了不中止服務的狀況,Redis的設計團隊採用了漸進式rehash的策略,每次只對原哈希表中的一小部分進行搬遷,這樣漸進式的進行,直到所有鍵值對都遷移到新的哈希表中。server

 

首先,對於key的查詢,咱們須要到原來的哈希表中進行查找,若是找到對應的value,直接返回就能夠了。若是沒有找到,那麼只有兩種可能,一個是這個鍵值對已經搬遷到新的哈希表了,另一種多是根本就不存在這個鍵值對,不管是哪一種可能,咱們都須要再去新哈希表中對他進行查找,若是找到了就返回,若是找不到說明這個鍵值對不存在。blog

 

步驟以下:
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]上了

相關文章
相關標籤/搜索