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;

哈希衝突

當兩個或者兩個以上的鍵被分配到哈希數組的同一個索引上,被稱爲哈希衝突。

哈希衝突的解決方法:

  1. 開放定址法(包括線性探查法、線性補償探測法、隨機探測)
  2. 拉鍊法,又稱鏈地址法

redis如何解決哈希衝突?
鏈地址法,每個哈希表結點都有一個next指針域,多個哈希表結點可以構成一個單鏈表,被分配到同一個索引的鍵可以使用這個next指針連起來,從而解決哈希衝突。

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