1,字典,又稱為符號表、關聯陣列、或對映,是一種用於儲存鍵值對的抽象資料結構。
2,redis的字典使用雜湊表作為底層實現,雜湊表的結構定義如下:
typedef
struct dicthtdicket;
table屬性是乙個陣列,陣列中的每個元素都是乙個指向dict.h/dictentry結構的指標,每個dictentry結構儲存著乙個鍵值對。sizemask的值和雜湊值一起決定乙個鍵應該被放到table陣列的哪個索引上面。
3,雜湊表節點結構:
typedef
struct dictentryv;
struct dictentry *next;
//指向下個雜湊表節點,形成鍊錶
}dictentry;
4,字典結構:
typedef
struct dictdict;
其中,type屬性和privdata屬性是針對不同型別的鍵值對,為建立多型字典而設定的:
type屬性是乙個指向dicttype結構的指標,每個dicttype結構儲存了一簇使用者操作特定型別鍵值對的函式,redis會為不同的字典設定不同的型別特定函式。
privdata屬性則儲存了需要傳給那些型別特定函式的可選引數。
rehashidx記錄的是rehash的進度,當前沒有rehash值是-1
5,要將乙個新的鍵值對新增到字典裡面時,需要做兩步:
1)使用字典設定的雜湊函式,計算鍵key的雜湊值。
2)使用雜湊表的sizemask屬性和雜湊值,計算出索引值。
隨著操作的不斷進行,雜湊表儲存的鍵值對會逐漸的增多或者減少,為了讓雜湊表的負載因子維持在乙個合理的範圍內,當雜湊表儲存的鍵值對數量太多或者太少時就需要進行rehash。主要通過如下3步:
1)為字典的ht[1]雜湊表分配空間,這個雜湊表的空間大小取決於要執行的操作,以及ht[0]當前包含的鍵值對數量:
如果執行擴充套件操作,那麼ht[1]的大小為第乙個大於等於ht[0].used*2的2的n次冪。
如果是收縮操作,那麼ht[1]的大小是第乙個大於等於ht[0].used的2的n次冪。
2)將儲存在ht[0]中的所有鍵值對rehash到ht[1]。
3)將ht[0]包含的所有鍵值對遷移到ht[1]之後,釋放ht[0],將ht[1]設定為ht[0],並在ht[1]新建立乙個空白雜湊表,為下一次rehash做準備。
6,需要注意的是,執行上面rehash的時候,系統應該是漸進式的,而不應該是集中式的。因為,如果雜湊表裡儲存的鍵值對不是4個而是幾億個,一次性rehash可能會導致伺服器在一段時間暫停服務任務。漸進式rehash的步驟如下:
1)為ht[1]分配空間,讓字典同時持有ht[0]和ht[1]兩個雜湊表
2)在字典中維持乙個索引計數器變數rehashidx,並將它的值設定為0,表示rehash工作開始
3)在rehash期間,每次對字典執行新增、刪除、查詢或者更新操作時,程式除了執行指定的操作外,還會順帶將ht[0]雜湊表在rehashidx索引上的所有鍵值對rehash到ht[1],這時程式將rehashidx屬性的值增1
4)隨著字典操作的不斷執行,最終在某個時間點上,ht[0]的所有鍵值對都會被rehash至ht[1],這時將rehashidx的值設定為-1,表示rehash操作已經完成。
7,漸進式rehash過程中,字典會同時使用ht[0],和ht[1]兩個雜湊表,所以在漸進式rehash進行期間,字典的刪除、查詢、等操作會在兩個雜湊表上進行。
在漸進式rehash執行期間,新新增到字典的鍵值對一律會被儲存到ht[1]裡面。
redis資料結構 字典
1.1 雜湊表資料結構typedef struct dictht dictht 1.2 字典資料結構typedef struct dict dict 2.1 擴縮容條件 2.2 擴容流程 2.3 漸進式rehash 2.4 漸進式rehash場景3.1 迭代器資料結構 迭代器主要用於遍歷字典,遍歷資...
Redis資料結構 字典
字典在redis中應用廣泛,redis資料庫的底層就是使用字典來實現的,對資料庫的增刪查改也都是建立在字典的操作之上的。此外,字典還是雜湊鍵的實現之一。雜湊表由dict.h dictht結構定義 typedef struct dictht dictht 雜湊表節點使用dictentry結構表示,每個...
redis資料結構之字典
字典 dictionary 其實和符號表 symbol table 關聯陣列 associative array 對映 map 是乙個東東,都是為了儲存鍵值對 k v pair 的資料結構,屌屌噠。php中因為能很方便的用關聯陣列,因此能寫出很多實用高效的 有空一定要去好好了解下php的關聯陣列是如...