redis设计与实现-字典

1.概述

字典dict相当于java中的HashMap,用来实现redis数据库和redis的hash类型value。

2.字典的实现

字典数据结构分为三部分,字典dict、哈希表dictht、节点dictEntry。一个dict包含两个dictht,一个dictht有多个dictEntry,每个dictEntry代表key-val。

2.1 源码

/*
 * 哈希表
 *
 * 每个字典都使用两个哈希表,从而实现渐进式 rehash 。
 */
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;

 


/*
 * 哈希表节点
 */
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;

2.2 hash算法

2.3 键冲突

当有两个及以上的键被分配到hash数组的同一个索引上面,程序将新添加的节点添加到链表的表头位置。

2.4 rehash

随着操作的不断执行,hash表的键值对的数量太多或者太少,程序需要对hash表的大小进行扩展和收缩。

扩展操作:ht[1]的大小等于ht[0].used*2的2的n次方幂

2.5 渐进式rehash

rehash并不是一次性、集中式的完成,而是分多次、渐进式的完成。这么做的原因是hash表的key可能数据量特别大,如果一次性rehash到另外一个ht的话,可能会让导致服务在一段时间停止。

1)dict字典中维护一个索引计数器变量rehashindex,并将它的值设置为0,表示rehash正式开始

2)在rehash期间,每次对字典执行添加、删除、查找或者更新操作时,程序除了执行指定操作,还会进行rehash操作。当rehash执行完成之后,rehashindex+1

3)最终在某个时间点上,rehash完成,rehashindex=-1

注:因为rehash过程会存在两个hash表,所以要查找一个键,程序会先从ht[0]查找,如果没找到就从ht[1]查找。新添加的键值都会保存在ht[1]

 

3.总结

感觉redis的hash表就跟java的HashMap差不多

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值