_dictReset(&d->ht[1]);//将ht[1].table设置为null
d->rehashidx = -1;
return 0;
}
/* 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)d->rehashidx);
//找到第一个不为空的数组
while(d->ht[0].table[d->rehashidx] == NULL) d->rehashidx++;
//指向该链表头
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;
nextde = de->next;
/* Get the index in the new hash table */
//得到在ht[1]中的索引号,通过相应的hash函数
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++;
}
return 1;
}
小结
Redis中的字典数据结构使用哈希表来实现,用来存储key-value键值元素;
字典使用两个哈希表,一般只使用ht[0],只有当Rehash时候才使用ht[0];
哈希表采用链表的方式解决键碰撞问题;
Redis的Rehash操作是渐进式的,服务器程序会主动Rehash,在查找、添加、删除元素等操作时也会在Rehash进行时执行一次rehash操作。
字典的内容实在太多,操作比较繁琐,应该是Redis中最复杂的底层数据结构了,本文分析的绝对不够深入,希望以后有时间再修改吧,暂时先这样。到目前为止,Redis六种内部数据结构,同时也是底层操作的实现讲解全部结束,后面的文章将进入五种基本数据类型指令的实现,字符串(String)、哈希表(Hash)、列表(List)、集合(Set)、有序集合(Sorted Set)的各种指令的实现。
我自己对Redis2.8.2源码的注释,有时间找个机会放出来。
最后感谢黄健宏(huangz1990)的Redis设计与实现及其他对Redis2.6源码的相关注释对我在研究Redis2.8源码方面的帮助。