redis基礎結構之字典

字典

作用: 數據庫和hash鍵

字典的結構
typedef struct dict {

    // 類型特定函數  
    //type以及privdata爲了創建多態字典存在
    dictType *type;

    // 私有數據
    void *privdata;

    // 哈希表 ht[1]主要用於rehash
    dictht ht[2];

    // rehash 索引
    // 當 rehash 不在進行時,值爲 -1
    int rehashidx; /* rehashing not in progress if rehashidx == -1 */

} dict;

dictType結構:

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;

字典的底層實現是hash表

typedef struct dictht {

    // 哈希表數組
    dictEntry **table;

    // 哈希表大小
    unsigned long size;

    // 哈希表大小掩碼,用於計算索引值
    // 總是等於 size - 1
    unsigned long sizemask;

    // 該哈希表已有節點的數量
    unsigned long used;
} dictht;

示意圖:
在這裏插入圖片描述
哈希表節點結構:

typedef struct dictEntry {

    // 鍵
    void *key;

    // 值
    union {
        void *val;
        uint64_t u64;
        int64_t s64;
    } v;

    // 指向下個哈希表節點,形成鏈表  採用鏈地址法解決衝突
    struct dictEntry *next;

} dictEntry;

字典示例圖:

在這裏插入圖片描述

字典索引值計算以及衝突解決方法

索引值計算: 如果index爲0 , 那麼存放在dictEntry*[0] 下
1).計算key的hash : hash = dict->type->hashFunction(key) 此處使用的hash算法爲(MurmurHash)
2).以key的hash計算索引 : index = hash & dict->ht[x].sizemask

衝突解決以及插入效率:
1).衝突解決:鏈地址法解決衝突
2).插入效率: 對於index相同的key,value按頭插法插入鏈

rehash

1.什麼時候會進行rehash?
負載因子 = ht[0].used / ht[0].size
1).當沒有進行持久化操作(bgsave和bgrewriteaof)時,負載因子大於等於1時會進行
2).當有在進行持久化操作(bgsave和bgrewriteaof)時,負載因子大於等於5會進行(目的:爲了避免在子進程存在期間進行rehash操作(寫時複製))
3).當負載因子小於0.1時,也會進行rehash操作

2.rehash操作:
1).ht[1]空間分配:
擴展: ht[1].size >= ht[0].used*2 的2^n冪 如ht[0].used= 4 ,那麼ht[1]= 8剛好2^3
收縮:ht[1].size >= ht[0].used 的2^n冪
2).漸進式rehash
1)).爲ht[1]分配空間
2)).將rehashindex值設爲0,表示rehash開始
3)).每次對字典的執行操做時,除了執行指定操作外,還會將rehashindex索引上指定的所有鍵值對rehash到ht[1]上,每次完成rehashindex加1
4)).字典完全rehash到ht[1]後,重設rehashindex爲-1,ht[1]變爲ht[0]
在漸進rehash階段會在ht[0]和ht[1]上進行刪除,更新,查找等操作(先ht[0]後ht[1]),所有的添加字典的操作都在ht[1]進行;

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章