Redis資料結構之字典
阿新 • • 發佈:2019-01-09
字典
描述
在字典中,一個鍵(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;