標籤:redis 雜湊
Redis資料類型之字典
標籤(空格分隔): redis
redis的字典
字典又稱符號表(symbol table),關聯陣列(associative array),或者映射(map)。是用於儲存索引值對的一種抽象資料結構。
字典的key是唯一的,對索引值對的操作基本都是基於key來操作的。redis中的資料庫底層是使用字典來實現的,對於資料庫的增刪改查都是基於字典來實現的。redis的雜湊鍵也是基於字典來實現的。
具體的實現是在src下的dict.h和dict.c檔案
字典的資料結構
雜湊表結點
/* * 雜湊表節點 */typedef struct dictEntry { // 鍵 void *key; // 值 union { void *val; uint64_t u64; int64_t s64; } v; // 指向下個雜湊表節點,形成鏈表 struct dictEntry *next;} dictEntry;
雜湊表的資料結構
/* * 雜湊表 */typedef struct dictht { // 雜湊表數組 dictEntry **table; // 雜湊表大小 unsigned long size; // 雜湊表大小掩碼,用於計算索引值 // 總是等於 size - 1 unsigned long sizemask; // 該雜湊表已有節點的數量 unsigned long used;} dictht;
字典的資料結構
/* * 字典 */typedef struct dict { // 類型特定函數 dictType *type; // 私人資料 void *privdata; // 雜湊表 dictht ht[2]; // rehash 索引 // 當 rehash 不在進行時,值為 -1 int rehashidx; /* rehashing not in progress if rehashidx == -1 */ // 目前正在啟動並執行安全迭代器的數量 int iterators; /* number of iterators currently running */} dict;
其中的dictType是一個struct
/* * 字典類型特定函數 */typedef 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;
// 雜湊表 dictht ht[2];
這裡的ht是一個包含兩項資料的數組,數組的每一項都是一個dictht雜湊表,一般情況下,只使用ht[0],ht[1]是在rehash的情況下使用。
雜湊演算法
當需要向字典添加一對索引值對時,程式首先根據字典的key計算出hash值和索引值,然後根據索引值,將包含新索引值對的雜湊表結點放到雜湊數組指定的索引位置上。
redis計算hash值和索引的方法如下
// 計算給定鍵的雜湊值#define dictHashKey(d, key) (d)->type->hashFunction(key) // 計算索引值idx = h & d->ht[table].sizemask;
雜湊衝突
當兩個或者兩個以上的鍵被分配到雜湊數組的同一個索引上,被稱為雜湊衝突。
雜湊衝突的解決方案:
- 開放定址法(包括線性探查法、線性補償探測法、隨機探測)
- 拉鏈法,又稱鏈地址法
redis如何解決雜湊衝突?
鏈地址法,每個雜湊表結點都有一個next指標域,多個雜湊表結點可以構成一個單鏈表,被分配到同一個索引的鍵可以使用這個next指標連起來,從而解決雜湊衝突。
著作權聲明:本文為博主原創文章,未經博主允許不得轉載。
Redis資料類型之字典