1. 程式人生 > >Redis資料結構之字典

Redis資料結構之字典

字典

描述

在字典中,一個鍵(key)可以和一個值(value)進行關聯(或者說將鍵對映為值),這些關聯的鍵和值就稱為鍵值對。

字典中的每個鍵都是獨一無二的,程式可以在字典中根據鍵查詢與之關聯的值,或者通過鍵來更新值,又或者根據鍵來刪除整個鍵值對,等等。 字典經常作為一種資料結構內建在很多高階程式語言裡面,但C並沒有內建這種資料結構,因此Redis構建了自己的字典實現。

字典在Redis中的應用相當廣泛,比如Redis的資料庫就是使用字典來作為底層實現的,對資料庫的增、刪、查、改操作也是構建在對字典的操作之上的。
例:
redis>SET msg "hello world"
OK


該鍵值對就是儲存在字典中的。字典還是雜湊鍵的底層實現之一,當一個雜湊鍵包含的鍵值對比較多,又或者鍵值對中的元素都是比較長的字串時,Redis就會使用字典作為雜湊鍵的底層實現。

實現

Redis的字典使用雜湊表作為底層實現,一個雜湊表裡面可以有多個雜湊表節點,而每個雜湊表節點就儲存了字典中的一個鍵值對。

雜湊表

雜湊表定義在原始碼的 dict.h中的 dictht中:

typedef struct dictht{
    //  雜湊表陣列     
    dictEntry **table;     
    //  雜湊表大小     
    unsigned long
size; // 雜湊表大小掩碼,用於計算索引值,總是等於size-1 unsigned long sizemask; // 該雜湊表已有節點的數量 unsigned long used; }dictht;

如圖,大小為4的空雜湊表:
這裡寫圖片描述

table屬性是一個數組,陣列中的每個元素都是一個指向dict.h/dictEntry結構的指標,每個dictEntry結構儲存著一個鍵值對。size屬性記錄了雜湊表的大小,也即是table陣列的大小,而used屬性則記錄了雜湊表目前已有節點(鍵值對)的數量。sizemask屬性的值總是等於size-1,這個屬性和雜湊值一起決定一個鍵應該被放到table陣列的哪個索引上面。

雜湊表節點

使用dictEntry表示

typedef struct dictEntry {
     //  鍵     
     void *key;     
     //  值     
     union{         
         void *val;         
         uint64_tu64;         
         int64_ts64;     
     } v;     
     //  指向下個雜湊表節點,形成連結串列
     struct dictEntry *next; 
} dictEntry;

如圖:
這裡寫圖片描述

  • key屬性儲存著鍵值對中的鍵,而v屬性則儲存著鍵值對中的值,其中鍵值對的值可以是一個指標,或者是一個uint64_t整數,又或者是一個int64_t整數。
  • next屬性是指向另一個雜湊表節點的指標,這個指標可以將多個雜湊值相同的鍵值對連線在一次,以此來解決鍵衝突(collision)的問題。

字典

在原始碼的dict.h中的dict裡實現

typedef struct dict {     
    //  型別特定函式     
    dictType *type;     
    //  私有資料
    void *privdata;     
    dictht ht[2];     
    // rehash 索引     
    // 當rehash 不在進行時,值為-1     
    in trehashidx; 
    /* rehashing not in progress if rehashidx == -1 */ 
} dict;