redis源码分析 --- 字典dict

字典dict

redis的字典使用哈希表作为底层实现,一个哈希表里面可以有多个哈希节点,而每个哈希表节点就保存了字典中的一个键值对。

  • dict结构定义

typedef struct dictEntry {
    void *key;                  /*! 键*/
    union {
        void *val;
        uint64_t u64;
        int64_t s64;
        double d;
    } v;                        /*! 值*/
    struct dictEntry *next;     /*! 采用链地址法解决节点冲突*/
} dictEntry;

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;

/* 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;     /*! 哈希表大小掩码,用于计算索引值,值为size-1*/
    unsigned long used;         /*! 哈希表中已使用节点的数量*/
} dictht;

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;

新的键值对添加到字典时,先根据键计算出哈希值和索引,然后再根据索引,将包含新键值对的哈希节点放到哈希表数组的制定索引上。

使用字典设置的哈希函数计算键key的哈希值

hash = (d)->type->hashFunction(key)

使用哈希表中的sizemask属性和哈希值,计算出索引值。此处使用&运算符而非%运算符,因为&运算符计算索引值idx性能更高。

idx = hash & d->ht[table].sizemask;

当有两个或以上数量的键被分到哈希表中的同一个索引上时,就会产生键冲突,redis采用链地址法来解决冲突。

  • rehash

随着操作不断进行,哈希表中保存的键值对会不断增多或减少,为了让哈希表的负载因子维持在一个合理的范围内,需要对哈希表的大小进行扩展或收缩,这个过程为rehash过程。

rehash的步骤为:

  1. 为ht[1]分配空间,大小取决于所要执行的操作和ht[0].used的值。
  2. 将ht[0]中的所有键值对都rehash到ht[1]上。
  3. 将ht[0]中所有键值对都迁移到ht[1]之后,ht[0]变为空表,释放ht[0],将ht[1]设置为ht[0]。

为了避免rehash对服务器性能造成影响,服务器不是一次性将ht[0]中所有键值对全部rehash到ht[1]中,而是多次渐进式进行。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值