3、字典

概念

一種用於保存鍵值對的抽象數據結構。又常被稱作 符號表、關聯數組、映射。Redis的數據庫就是使用字典作爲底層實現的、字典還是哈希鍵的底層實現之一。

實現

由於字典底層是有哈希表(分清哈希表和哈希鍵)實現,首先介紹哈希表

1、哈希表

typedef struct dictht{
    dictEntry **table;        //指向哈希表數組
    unsigned long size;       //hash表大小,上述數組的長度
    unsigned long sizemark;   //哈希表掩碼,用於計算索引值,大小恆爲size-1
    unsigned long used;       //已有的節點數量
}dictht;

索引計算方法,假設hash值爲8,size=4,sizemark=3,index = 8&3=0;

算法主頁:點擊打開鏈接

2、hash表節點(鍵值對+指向下一個節點的next指針),next指針將多個hash值相同的鍵值對連接在一起,以此解決鍵衝突的問題,這種方法稱爲“鏈地址法”。爲了速度考慮,總是將新節點添加到鏈表的表頭位置。

3、字典

typedef struct dict{
    dictType *type;    //類型特定函數
    void *privdata;    //私有數據,保存傳給那些類型特定函數的可選參數,這兩個參數是爲了實現多態而實現的
    dictht ht[2];      //hash表,平時只用ht[0],ht[1]是在rehash時候使用的
    int trehashidx;    //rehash索引,沒有進行rehash的時候,值爲-1;記錄rehash的進度
}

rehash

首先了解一下負載因子,load_fact = ht[0].used/ht[0].size    //節點數量/hash表的大小

爲什麼要rehash:hash表中保存的鍵會增多或者減少,需要將負載因子維護在一個合理的範圍中。

rehash的步驟:1、爲ht[1]分配空間,這個空間大小取決於即將執行的操作和鍵值對的數量(ht[0].used)

                                如果是擴展操作,ht[1]的大小爲大於等於ht[0].used*2的最小的2的整數次冪

                                如果是收縮操作,ht[1]的大小爲大於等於ht[0].used的2的最小的整數次冪

                         2、重新計算hash值,將鍵值對擺放到ht[1]中

                         3、釋放ht[0],將ht[1]置爲ht[0],在ht[1]創建空白hash表,爲下一次rehash做準備

rehash的影響因素:load_fact,BGSAVE和BGREWRITEAOF是否正在執行,後兩者的執行是作爲redis的子進程運行的,這時redis會提高負載上限,避免在子進程存在期間進行rehash。

漸進式rehash

概念:爲了避免造成服務器性能上的影響,分批次的rehash;

即同時持有ht[0]和ht[1],在每次執行增刪該查的操作後,對ht[0]rehash索引處的所有鍵值對進行rehash操作。所以,漸進式rehash過程中,所有的操作是發生在兩張hash表中的,但是所有的新增節點都會被放在ht[1]上。把rehash均攤到了每次的操作上。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章