Dict字典
数据结构
哈希表结构
作为字典的底层实现
typedef struct dictht {
// 哈希表数组
dictEntry **table;
// 哈希表大小
unsigned long size;
// 哈希表大小掩码,用于计算索引值
// 总是等于size-1
unsigned long sizemask;
//该哈希表已有的节点数
unsigned long used;
} dictht;
哈希表节点
typedef struct dictEntry {
// 键
void *key;
// 值
union {
void *val;
uint64_tu64;
int64_ts64;
} v;
// 指向下个哈希表节点,形成链表
struct dictEntry *next;
} dictEntry;
字典
typedef struct dict {
// 类型特定函数
dictType *type;
// 私有数据
void *privdata;
// 哈希表
dictht ht[2];
// rehash索引,当为-1表示没有在进行rehash
in trehashidx;
}
一个普通状态下的字典
问题
哈希算法
MurmurHash
算法
解决冲突
链地址法
,将发生冲突的key插入到已有的key之前
Rehash(渐进式)
为了让负载因子(load factor) 维持在一个合理的范围
过程中是渐进式,并不是一次性、集中的完成。
扩容
将数据从ht[0]
向ht[1]
迁移
触发时间节点
- 服务器目前没有执行 BGREWRITEAOF 或者 BGSAVE 命令,且哈希表的负载因子大于等于 1
- 服务器目前正在执行 BGSAVE 或者 BGREWRITEAOF 命令, 并且哈希表的负载因子大于等于 5
工作流程
- 将给
ht[1]
分配一个ht[0]
2倍空间的大小 - 渐进式迁移
k-v
- 释放
ht[0]
,然后将ht[1]
交换到ht[0]
,分配一个空白的ht[1]
缩容
- 哈希表的负载因子小于 0.1 时, 程序自动开始对哈希表执行收缩操作
在执行 BGREWRITEAOF 或者 BGSAVE 命令 时,Redis 会为当前服务器进程创建一个子进程,所以在子进程存在期间,会提高执行扩容的负载因子,因为这样可以避免在子进程存在期间进行哈希表的扩容操作,从而避免不必要的内存写入操作,最大限度的节约内存,提高效率。
优势
能够以O(1)时间复杂度来获取结果
如果hash冲突多的话导致在找到指定key
的时候可能需要遍历一下链表的结果。
转载:https://blog.csdn.net/weixin_42322309/article/details/105879382
查看评论