字典哈希表的实现原理_redis字典实现哈希表初探

Redis字典在redis中被广泛运用,作为redis字典底层实现的哈希表结构是怎样的呢,今天结合源码初步了解下

typedef struct dictEntry {
    void *key;
    union {
        void *val;
        uint64_t u64;
        int64_t s64;
        double d;
    } v;
    struct dictEntry *next;
} dictEntry;

redis哈希表节点定义了一个键值对的存储,next指针指向另一个哈希表节点,用于解决键冲突。当计算出来不同key值 key1 key2的索引值相同时,就需要通过链地址法把不同的键值对链在一起。由于next链表只有头指针没有尾指针,所以当key值发生冲突时,总是将新节点采用头插法添加到表头。

48b74283767385a25d0f1e343628693c.png
链地址法解决键冲突
/* This is our hash table structure. Every dictionary has two of this as we
 * implement incremental rehashing, for the old to the new table. */
typedef struct dictht {
    dictEntry **table;
    unsigned long size;
    unsigned long sizemask;
    unsigned long used;
} dictht;

redis哈希表中table是一个指针数组,每个元素都是指向dictEntry键值对的指针,size记录哈希表的大小,used记录哈希表当前已存储的键值对数,sizemask用于计算key的索引,总是等于size-1。

计算key值索引index
hash=dict->type->hashFunction(key);
index=hash & dict->ht[x].sizemask;
typedef struct dict {
    dictType *type;
    void *privdata;
    dictht ht[2];
    long rehashidx; /* rehashing not in progress if rehashidx == -1 */
    unsigned long iterators; /* number of iterators currently running */
} dict;

redis字典包好二个dictht哈希表,一般字典只会使用ht[0]哈希表,但在哈希表扩展或收缩时进行rehash时就会使用ht[1]

7da16c3296aeb84db9804efc33b80ef2.png
没有进行rehash动作的字典
typedef struct dictType {
    uint64_t (*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;

dictType结构定义了一组操作键值对的函数,hashFunction就是对key计算hash值的函数,

redis使用MururHash2哈希算法,该算法在任何时候都能很好的给出key的随机分布性,减少key的冲突,并且执行速度快。

当哈希表保存的键值对太多或太少时,需要对哈希表进行扩展或收缩保证hash表的负载因子合理。

redis字典rehash过程:

1->字典的ht[1]哈希表分配空间,扩展或收缩;

2->将ht[0]上的所有键值对计算哈希值和索引值rehash对ht[1]上;

3->释放ht[0],ht[0]指向新分配的ht[1],ht[1]指向新的空哈希表;

/* If safe is set to 1 this is a safe iterator, that means, you can call
 * dictAdd, dictFind, and other functions against the dictionary even while
 * iterating. Otherwise it is a non safe iterator, and only dictNext()
 * should be called while iterating. */
typedef struct dictIterator {
    dict *d;
    long index;
    int table, safe;
    dictEntry *entry, *nextEntry;
    /* unsafe iterator fingerprint for misuse detection. */
    long long fingerprint;
} dictIterator;
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值