redis6.0源码学习 (四)dict
文章目录
redis dict主要实现文件为src/dict.c 和dict.h,实现了 insert / del / replace / find / get-random-element操作。哈希表会自动以调整大小,冲突通过链接处理。
1、数据结构
1.1 dictht
在看dict得结构前,先看下dict中的dicht (hash表)结构,下面是hash表结构的定义:
typedef struct dictht { //hash表结构定义,每一个dict有两个,在rehash过程中会用到两个。
dictEntry **table; // 哈希表节点指针数组(俗称桶,bucket)
unsigned long size; // 指针数组的大小
unsigned long sizemask; // 指针数组的长度掩码,用于计算索引值
unsigned long used; // 哈希表现有的节点数量
} dictht;
1.2 dictEntry
下面是hash表节点的定义
typedef struct dictEntry {
void *key; //键
union {
void *val;
uint64_t u64;
int64_t s64;
double d;
} v; //值
struct dictEntry *next;//在存在hash冲突的时候,用来链接具有相同hash值得key/val对,如下图所示。
} dictEntry;
下图展示了dictEntry在dictht中存储示意图:
1.3 dict
下面是redis字典定义的结构:
typedef struct dict {
dictType *type;
void *privdata;
dictht ht[2]; //两个hash表
long rehashidx; /*记录 rehash 进度的标志,值为 -1 表示 rehash 未进行*/
unsigned long iterators; /* 当前正在运作的安全迭代器数量*/
} dict;
dictType *type
:一个指向dictType结构的指针(type)。它通过自定义的方式使得dict的key和value能够存储任何类型的数据。void *privdata
:一个私有数据指针。由调用者在创建dict的时候传进来。dictht ht[2]
:两个哈希表,只有在rehash的过程中,ht[0]和ht[1]才都有效。一般情况下,只有ht[0]有效,ht[1]里面没有任何数据。long rehashidx
:当前rehash索引(rehashidx)。如果rehashidx = -1,表示当前没有在rehash过程中;否则,表示当前正在进行rehash,且它的值记录了当前rehash进行到哪一步了。unsigned long iterators
:当前正在进行遍历的iterator的个数。这不是我们现在讨论的重点,暂时忽略。
下面是字典类型定义:
typedef struct dictType {
//对key进行哈希值计算的哈希算法
uint64_t (*hashFunction)(const void *key);
//keyDup和valDup: 分别定义key和value的拷贝函数,用于在需要的时候对key和value进行深拷贝,而不仅仅是传递对象指针
void *(*keyDup)(void *privdata, const void *key);
void *(*valDup)(void *privdata, const void *obj);
//定义两个key的比较操作,在根据key进行查找时会用到
int (*keyCompare)(void *privdata, const void *key1, const void *key2);
//keyDestructor和valDestructor: 分别定义对key和value的析构函数
void (*keyDestructor)(void *privdata, void *key);
void (*valDestructor)(void *privdata, void *obj);
} dictType;
下面是dict的示意图:
2、dict的创建
/* Reset a hash table already initialized with ht_init().
* NOTE: This function should only be called by ht_destroy(). */
static void _dictReset(dictht *ht)
{
ht->table = NULL;
ht->size = 0;
ht->sizemask = 0;
ht->used = 0;
}
/* Create a new hash table */
dict *dictCreate(dictType *type,
void *privDataPtr)
{
dict *d = zmalloc(sizeof(*d));
_dictInit(d,type,privDataPtr);
return d;
}
/* Initialize the hash table */
int _dictInit(dict *d, dictType *type,
void *privDataPtr)
{
_dictReset(&d->ht[0]);
_dictReset(&d->ht[1]);
d->type = type;
d->privdata = privDataPtr;
d->rehashidx = -1;
d->iterators = 0;
return DICT_OK;
}
3、 元素的查找、插入和删除
4、 rehash过程
5、总结
待续。。。。