字典就是我們熟悉的map,鍵值對(key-value pair)的抽象數據結構。Redis數據庫就是使用字典來作爲底層實現的。
先介紹下數據結構:
1.哈希表
typeof struct dictht {
//哈希表數組
dictEntry **table;
//哈希表大小
unsigned long size;
//哈希表大小掩碼,用於計算索引
//總是等於size-1
unsigned long sizemask;
//已有節點數量
unsigned long used;
} dictht;
這種數據結構很好理解,和Java裏面HashMap實現差不多。哈希表裏面每個節點都是一個entry對象。
2.哈希表節點
typeof struct dictEntry {
//鍵
void *key;
//值
union {
void *val;
unit64_t u64;
int64_t s64;
} v;
//指向下個哈希表節點,形成鏈表
struct dictEntry *next;
} dictEntry;
key屬性存着鍵值對中的鍵,v屬性存值。鍵可以是一個指針,也可以是一個unit64_t整數,或是一個int^4_t整數。C語言沒了解過,這種奇怪的整數也不知道什麼意思,姑且理解爲Java裏面的hashCode吧。
next屬性指向鏈表中的下一個節點,這點和Java一樣,當多個對象哈希值相同時,就造成hash衝突,多個對象的索引值都落在同一索引下標上,該節點的數據結構爲鏈表,需要遍歷該鏈表才能找到對應元素。
3.字典數據結構
typeof struct dict {
//類型特定函數
dictType *type;
//私有數據
void *privdata;
//哈希表
dictht ht[2];
//rehash索引
//當rehash不再進行時,值爲-1
int rehashidx;
} dict;
type屬性和privdata屬性針對不同類型的鍵值對,爲創建多態字典設置的。
type屬性是一個指向dictType結構的指針,每個dictType保存了一簇用於操作特定類型鍵值對的函數,Redis會爲用途不同的字典設置不同的類型特定函數。
privdata屬性保存了需要傳給那些類型特定函數的可選參數。
typeof struct dictType {
//計算哈希值的函數
unsigned int (*hashFunction) (const void *key);
//複製鍵的函數
void *(*keyDup) (void *privdata, const void *key);
//複製值的函數
void *(*valDup)(void *privdata, const void *obj);
//對比鍵的函數
int (*keyCompare) (void *privdata, const void *key1, const void *key2);
//銷燬鍵的函數
void (*keyDestructor) (void *privdata, void *key);
//銷燬值的函數
void (*valDestructor) (void *privdata, void *obj);
} dictType;
ht屬性是一個包含2個索引的數組,每個位置都是一個dictht哈希表,一般使用ht[0],ht[1]用於存放對ht[0]哈希表進行rehash的結果。
rehashidx記錄目前rehash進度,當前沒有執行rehash,值爲-1。