Redis源码学习——安全迭代器和非安全迭代器(二)


通过上一篇博客的分析,我们已经大概知道 字典迭代器 的定义和用处了,也了解到安全迭代器和非安全迭代器的定义上的区别,还有安全迭代器的作用:给dict设置iterators++(dict里面的变量),这样字典的各种操作就不会执行单步rehash操作。

我们接下来就来讨论一下:为什么设置 iterators++ 之后就不能对字典进行rehash操作呢??
还有就是 安全迭代器和非安全迭代器的应用场景分别是怎样的??

一、iterators 变量与单步rehash

1.1 iterators 变量的定义

我们首先来看一下 iterators 变量是在哪个结构体中定义的:

 * 字典
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;

可以看到,这个 iterators 变量 是在定义字典的时候用到的变量,也就是说, iterators 变量是字典的一个属性,这个iterators值表示目前正在运行的安全迭代器的数量,所以每当dictNext(dictIterator *iter)函数中调用到一次安全迭代器,这个值就会自增加一。

1.2 单步rehash

那这个 iterators值 和单步rehash又有什么关系呢,我们来看一下单步rehash的函数定义:

/*
 * 在字典不存在安全迭代器的情况下,对字典进行单步 rehash 。        
 *
 * 字典有安全迭代器的情况下不能进行 rehash ,
 * 因为两种不同的迭代和修改操作可能会弄乱字典。
 *
 * 这个函数被多个通用的查找、更新操作调用,
 * 它可以让字典在被使用的同时进行 rehash 。
 *
 * T = O(1)
 */
static void _dictRehashStep(dict *d) {
   
   
    if (d->iterators == 0) dictRehash(d,1);  //iterators == 0表示字典不存在安全迭代器
}

从上面的代码和注释,我们可以看到,只有当 iterators == 0,表示字典不存在安全迭代器时,才能调用 dictRehash() 函数来对字典进行rehash。
那什么时候会调用到这个 _dictRehashStep 函数呢,看下面的代码:

// 如果条件允许的话,进行单步 rehash
    if (dictIsRehashing(d)) _dictRehashStep(d); !!!!!!!!!!!!
.......
#define dictIsRehashing(ht) ((ht)->rehashidx != -1)    

(上面的代码是随便截取下来的,没有前后的逻辑性,只是为了说明问题而已)
从上面的代码块我们可以看到,当字典中的 rehashidx 参数不等于 -1 ,字典正在进行 rehash时,才能调用 _dictRehashStep 函数进行单步rehash操作。

那为啥调用dictRehash(d,1)函数之后就能执行所谓的“单步rehash”了呢,我们下面来看一下dictRehash() 函数的定义:

1.3 dictRehash() 函数的定义

 * 执行 N 步渐进式 rehash 。
 *
 * 返回 1 表示仍有键需要从 0 号哈希表移动到 1 号哈希表,
 * 返回 0 则表示所有键都已经迁移完毕。
 *
 * 注意,每步 rehash 都是以一个哈希表索引(桶)作为单位的,!!!!!!!!!!!!!
 * 一个桶里可能会有多个节点,
 * 被 rehash 的桶里的所有节点都会被移动到新哈希表。
 *
 * T = O(N)
 */
int dictRehash(dict *d, int n) {
   
   

    // 只可以在 rehash 进行中时执行
    if (!dictIsRehashing(d)) return 0;

    // 进行 N 步迁移
    // T = O(N)
    while(n--) {
   
   
        dictEntry *de, *nextde;

        // 如果 0 号哈希表为空,那么表示 rehash 执行完毕
        // T = O(1)
        if (d->ht[
评论 6
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值