# 结构
# 用处
- 数据库
- 哈希键
- 其他
# 定义
typedef struct dict { | |
// 类型特定函数 | |
dictType *type; | |
// 私有数据,保存了需要传给那些类型特定函数的可选参数 | |
void *privdata; | |
// 哈希表 | |
dictht ht[2]; | |
//rehash 索引,当 rehash 不在进行时,值为 -1 | |
int rehashidx; | |
} 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 void *key1. const void *key2); | |
// 销毁键的函数 | |
void (*keyDestructor)(void *privdata, void *key); | |
// 销毁值的函数 | |
void (*valDestructor)(void *privdata, void *obj); | |
} dictType; | |
typedef struct dictht { | |
// 哈希数组 | |
dictEntry **table; | |
// 哈希表大小 | |
unsigned long size; | |
// 哈希表大小掩码,用于计算索引值,等于 size - 1 | |
unsigned long sizemask; | |
// 哈希表已有节点数量 | |
unsigned logn used; | |
} dictht; | |
typedef struct dictEntry { | |
// 键 | |
void *key; | |
// 值 | |
union { | |
void *val; | |
uint64_tu64; | |
int64_ts64; | |
} v; | |
// 下一个节点 | |
struct dictEntry *next; | |
} dictEntry; |
# rehash
步骤:
- 为 ht [1] 分配空间
- 如果是扩展操作,大小扩为第一个不小于 h [0].used*2 的 2 的倍数
- 如果是收缩操作,大小为第一个不小于 h [0].used 的 2 的倍数
- 移动 ht [0] 的数据到 ht [1]
- 释放 ht [0],将 ht [1] 变为 ht [0],并为 h [1] 新建一个空白哈希表
扩展条件:
- 服务器没有在执行 BGSAVE 或 BGREWRITEAOF 命令,并且哈希表的负载因子大于等于 1
- 服务器在执行 BGSAVE 或 BGREWRITEAOF 命令,并且哈希表的负载因子大于等于 5
收缩条件:
- 哈希表的负载因子小于 0.1
# 渐进式 rehash
rehash 的步骤 2 不是一次性完成,是分多次、渐进式的完成的,为了防止哈希表中数据太多影响性能。
步骤:
- 为 ht [1] 分配空间
- rehashidx 设为 0
- rehash 期间,每次对字典执行添加、删除、查找、更新操作时,还要将 ht [0].table [rehashidx] 上的数据移动到 ht [1],并将 rehashidx 加 1,添加操作要添加到 ht [1] 中,保证 ht [0] 上的数据只减不增
- 当完成所有数据的移动后,将 rehashidx 设为 -1