【面试】Redis底层数据结构——Dict字典

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
工作流程
  1. 将给ht[1]分配一个ht[0]2倍空间的大小
  2. 渐进式迁移k-v
  3. 释放ht[0],然后将ht[1]交换到ht[0],分配一个空白的ht[1]

缩容

  • 哈希表的负载因子小于 0.1 时, 程序自动开始对哈希表执行收缩操作

在执行 BGREWRITEAOF 或者 BGSAVE 命令 时,Redis 会为当前服务器进程创建一个子进程,所以在子进程存在期间,会提高执行扩容的负载因子,因为这样可以避免在子进程存在期间进行哈希表的扩容操作,从而避免不必要的内存写入操作,最大限度的节约内存,提高效率。


优势

能够以O(1)时间复杂度来获取结果

如果hash冲突多的话导致在找到指定key的时候可能需要遍历一下链表的结果。

猜你喜欢

转载自blog.csdn.net/weixin_42322309/article/details/105879382