定义
哈希表
typedef struct dictht {
dictEntry **table; // 哈希表数组
unsigned long size; // 哈希表大小
unsigned long sizemask; // 哈希表大小掩码,用于计算索引值,总是等于size - 1
unsigned long used; // 哈希表已有节点的数量
}dictht;
哈希表节点
typedef struct dictEntry {
void *key; // 键
union {
void *val;
uint64_t u64;
int64_t s64;
struct dictEntry *next;
}v; // 值
struct dictEntry *next; // 指向下个哈希表节点,形成链表
}dictEntry;
字典
typedef struct dict {
dictType *type; // 类型特定函数
void *private; // 私有数据
dictht ht[2]; // 哈希表
int trehashidx; // rehash索引,当rehash不在进行时,值为-1
}dict;
typedef struct dictType {
unsigned int (*hashFunction)(const void *key);
void *(*keyDup)(void *privdata, const void *key);
void *(*valDup)(void *privdata, const void *obj);
int (*keyCompare)(void *privdata, const *key1, const void *key2);
void (*keyDestructor)(void *privdata, void *key);
void (*valDestructor)(void *privdata, void *obj);
}dictType;
普通状态下的字典图示

rehash
操作步骤
- 为ht[1]哈希表分配空间,哈希表的空间大小取决于要执行的操作,以及ht[0].used
扩展操作:ht[1]的大小为第一个大于等于
收缩操作:ht[1]的大小为第一个大于等于
- ht[0]中所有的键值对都迁移到ht[1]:重新计算键的哈希值和索引值
- 当ht[0]中所有键值对都迁移到了ht[1]之后,释放ht[0],将ht[1]设置为ht[1],ht[1]新创建空白哈希表
渐进式rehash
操作步骤
- 为ht[1]分配空间,让字典同时拥有ht[0]和ht[1]两个hash表
- 在字典中维持一个索引计数器变量rehashidx = 0,表示rehash工作开始
- 在rehash进行期间,每次对字典执行添加、删除、查找、更新操作时,程序既执行指定操作,也会将ht[0]中索引值为rehashidx的键值对rehash到ht[1],当rehash工作完成,rehashidx++
- 随着字典操作的不断执行,最终在某个时间点上,ht[0]所有键值对都会rehash到ht[1],此时rehashidx置为-1,表示rehash操作已完成
参考
《Redis设计与实现》