字典在Redis中的應用至關普遍,好比Redis的數據庫就是使用字典做爲底層實現的,對數據庫的增刪該查也是構建在對字典的操做之上。算法
Redis的字典使用哈希表做爲底層實現,一個哈希表裏能夠有多個哈希表節點,而每一個哈希表節點就保存了字典中的一個鍵值對數據庫
哈希表的數據結構數組
哈希表節點服務器
字典的數據結構數據結構
該圖展現了一個普通狀態下(沒有進行rehash)的字典spa
當要將一個新的鍵值對添加到字典裏面時,程序須要先根據鍵值對計算出哈希值和索引值,而後再根據索引值,將包含鍵值對的哈希表節點放到哈希表數組指定的索引上面。索引
//計算hash值hash
hash=dict->type->hashFunction(key);io
// 計算索引擴展
index = hash & dict->ht[x].sizemask;
例如
index= hash & dict->ht[x].sizemask=2;
當有兩個或兩個以上的數量的鍵被分配到了hash表數組的同一個索引上面時,就發生衝突
Redis採用鏈地址法來解決hash衝突
例如
咱們對下圖的ht[0]進行擴展操做,那麼將執行以下步驟
1 ht[0].used=4,ht[1]的size 將設置爲8,以下圖
2 將ht[0]包含的四個鍵值對都rehash 到ht[1]。以下圖
3 釋放ht[0],並將ht[1] 設置ht[0],而後將ht[1]分配一個空白的hash表
上面哈希表的擴展須要將ht[0]裏面的全部鍵值對rehash到ht[1]裏面,可是這個rehash 動做並非一次性的完成,而是分屢次完成。這樣作的緣由在於,若是ht[0]裏面只保存四個鍵值對,Redis 服務器瞬間就能完成,若是hash表裏的鍵值對是四千萬,四億,龐大的計算量會讓服務器在一段時間內中止服務。
漸進式步驟以下
省略步驟。。。。。。
字典會同時使用ht[0]和ht[1]兩個哈希表,因此在漸進式rehash 進行期間,字典的查找,刪除,修改,會在兩個表上進行。例如查找一個鍵值對,會如今ht[0]中查找,沒有找到會到ht[1]查找。