redis笔记-字典

1.字典结构

typedef struct dict {
//类型特定函数
    dictType *type;
//私有数据, 为特定函数传参数
    void *privdata;
//哈希表 ht[0]正在用的哈希表 ht[1] rehash时会用到
    dictht ht[2];
//-1时没有进行rehash,否则代表rehash的索引
    long rehashidx; /* rehashing not in progress if rehashidx == -1 */
    int iterators; /* number of iterators currently running */
} dict;

2.哈希表

typedef struct dictht {
//哈希节点的数组
    dictEntry **table;
//大小
    unsigned long size;
//哈希表的掩码 用于计算索引值(将键值对放在哪个位置)
    unsigned long sizemask;
//已有节点数量
    unsigned long used;
} dictht;

3.哈希表节点

typedef struct dictEntry {
//键
    void *key;
//值
    union {
        void *val;
        uint64_t u64;
        int64_t s64;
        double d;
    } v;
//指向下一个hash节点,防止hash冲突
    struct dictEntry *next;
} dictEntry;

4. 解决键冲突

什么是哈希冲突: 至少两个键hash后分配到了哈希表数组的同一个索引上

redis使用链表发解决这个问题,当发生冲突时利用节点的next解决问题

5. rehash

当发生rehash时,先为ht[1]分配空间,在进行hash表增删改查时逐渐将ht[0]的键值对移到ht[1]上(配合rehashidx, 记录索引的位置),新增的键值对直接放到ht[1]上,保证ht[0]只减不增. 当ht[0]为空时,释放ht[0],ht[1]置为ht[0]

6.rehash源码

//d 字典 n rehash的数量
int dictRehash(dict *d, int n) {
//最多空桶的数量
    int empty_visits = n*10; /* Max number of empty buckets to visit. */
//如果没有rehash(判断rehashindex 是否是-1) 函数对出
    if (!dictIsRehashing(d)) return 0;

//while循环 n减减 并且ht[0]还有节点
    while(n-- && d->ht[0].used != 0) {
        dictEntry *de, *nextde;

        /* Note that rehashidx can't overflow as we are sure there are more
         * elements because ht[0].used != 0 */
        assert(d->ht[0].size > (unsigned long)d->rehashidx);
//跳过空桶
        while(d->ht[0].table[d->rehashidx] == NULL) {
            d->rehashidx++;
            if (--empty_visits == 0) return 1;
        }
//获取节点
        de = d->ht[0].table[d->rehashidx];
        /* Move all the keys in this bucket from the old to the new hash HT */
        while(de) {
            unsigned int h;
//存储下一个节点,方便while循环
            nextde = de->next;
            /* Get the index in the new hash table */
//计算节点在ht[1]中的索引位置
            h = dictHashKey(d, de->key) & d->ht[1].sizemask;
//节点做为头节点 存储在ht[1]中
            de->next = d->ht[1].table[h];
            d->ht[1].table[h] = de;
//修改节点的数量
            d->ht[0].used--;
            d->ht[1].used++;
            de = nextde;
        }
        d->ht[0].table[d->rehashidx] = NULL;
//下一个位置
        d->rehashidx++;
    }

    /* Check if we already rehashed the whole table... */
//判断rehash是否结束
    if (d->ht[0].used == 0) {
//释放ht[0]
        zfree(d->ht[0].table);
//ht[1]变为ht[0]
        d->ht[0] = d->ht[1];
        _dictReset(&d->ht[1]);
//rehash结束
        d->rehashidx = -1;
        return 0;
    }

    /* More to rehash... */
    return 1;
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值