程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> C語言 >> C++ >> C++入門知識 >> Redis源碼學習之[哈希字典]

Redis源碼學習之[哈希字典]

編輯:C++入門知識

介紹 Redis的哈希字典通過key值來找對應的value。需要注意的是Redis的字典是如何進行rehash的。 源碼 dict.h dict.c 數據結構   如上圖所示,哈希字典用dict結構體表示,其中含有兩個哈希表,主要用於進行rehash操作。同時哈希表使用量表的方式解決沖突。具體的數據結構如下: [cpp]   /*   * 哈希表節點   */   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進行分散操作可以避免阻塞導致的性能急劇下降。www.2cto.com 迭代器 迭代器的屬性如果是安全的則表明可以在迭代的過程中進行dictAdd等其他的操作,而如果迭代器是不安全的則只能進行next的操作。 同時Redis限制在有迭代器訪問字典的時候進行rehash,因為這樣會造成對一個元素訪問多次。但是在rehash的過程中可以隨時的對字典進行遍歷,一旦迭代器開始遍歷字典了,rehash就會暫停知道沒有迭代器在對字典進行遍歷為止。

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved