Redis源碼學習之【雜湊字典】

來源:互聯網
上載者:User
介紹

Redis的雜湊字典通過key值來找對應的value。需要注意的是Redis的字典是如何進行rehash的。

源碼dict.h dict.c資料結構


如所示,雜湊字典用dict結構體表示,其中含有兩個雜湊表,主要用於進行rehash操作。同時雜湊表使用量表的方式解決衝突。具體的資料結構如下:

/* * 雜湊表節點 */typedef struct dictEntry {    // 鍵    void *key;    // 值    union {        void *val;        uint64_t u64;        int64_t s64;    } v;    // 鏈往後繼節點    struct dictEntry *next; } dictEntry;/* * 特定於類型的一簇處理函數 */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;/* * 雜湊表 */typedef struct dictht {    // 雜湊表節點指標數組(俗稱桶,bucket)    dictEntry **table;          // 指標數組的大小    unsigned long size;         // 指標數組的長度掩碼,用於計算索引值    unsigned long sizemask;     // 雜湊表現有的節點數量    unsigned long used;     } dictht;/* * 字典 * * 每個字典使用兩個雜湊表,用於實現漸進式 rehash */typedef struct dict {    // 特定於類型的處理函數    dictType *type;    // 類型處理函數的私人資料    void *privdata;    // 雜湊表(2個)    dictht ht[2];           // 記錄 rehash 進度的標誌,值為-1 表示 rehash 未進行    int rehashidx;    // 當前正在運作的安全迭代器數量    int iterators;      } dict;/* * 字典迭代器 * * 如果 safe 屬性的值為 1 ,那麼表示這個迭代器是一個安全迭代器。 * 當安全迭代器正在迭代一個字典時,該字典仍然可以調用 dictAdd 、 dictFind 和其他函數。 * * 如果 safe 屬性的值為 0 ,那麼表示這不是一個安全迭代器。 * 如果正在運作的迭代器是不安全迭代器,那麼它只可以對字典調用 dictNext 函數。 */typedef struct dictIterator {    // 正在迭代的字典    dict *d;                    int table,              // 正在迭代的雜湊表的號碼(0 或者 1)        index,              // 正在迭代的雜湊表數組的索引        safe;               // 是否安全?    dictEntry *entry,       // 當前雜湊節點              *nextEntry;   // 當前雜湊節點的後繼節點} dictIterator;

分析

rehash

在字典中使用了兩個hash表就是為了方便進行rehash的,rehash主要有兩種方式,一是由後台調用cron進行按照100步進進行hash,二是在進行添加刪除字典中的元素的時候進行1步的hash。

這裡每一次的hash的步進是以真箇hash key對應的鏈表為單位的,也就是說1步進的rehash是將原來hash表中的一個key鏈表進行rehash到新的雜湊表中的位置。這裡可以看出Redis在此處是犧牲了記憶體但是換來了效能的響應。將rehash進行分散操作可以避免阻塞導致的效能急劇下降。

迭代器

迭代器的屬性如果是安全的則表明可以在迭代的過程中進行dictAdd等其他的操作,而如果迭代器是不安全的則只能進行next的操作。

同時Redis限制在有迭代器訪問字典的時候進行rehash,因為這樣會造成對一個元素訪問多次。但是在rehash的過程中可以隨時的對字典進行遍曆,一旦迭代器開始遍曆字典了,rehash就會暫停知道沒有迭代器在對字典進行遍曆為止。


聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.