Redis源码分析(三)——Redis数据结构-字典
时间:2022-05-03
本文章向大家介绍Redis源码分析(三)——Redis数据结构-字典,主要内容包括1. 数据结构、1.2 哈希表节点、1.3 字典、2. 哈希算法、3. rehash、3.2 新哈希表大小的计算公式、3.3 rehash过程、3.4 渐进式rehash、基本概念、基础应用、原理机制和需要注意的事项等,并结合实例形式分析了其使用技巧,希望通过本文能帮助到大家理解应用这部分内容。
1. 数据结构
1.1 哈希表
typedef struct dictht{
dictEntry **table;
unsigned long size;
unsigned long sizemask;
unsigned long used;
} dictht;
-
table
:存储节点的数组 -
size
:table数组的长度 -
sizemask
:size-1,用于在添加节点时计算节点在table中的位置 -
used
:节点数量
1.2 哈希表节点
typedef struct dictEntry{
void *key
union {
void *val;
unit64_t u64;
int64_t s64;
}v;
struct dictEntry *next
} dictEntry;
-
key
:节点的key -
union
:节点的value(可以是指针、unit64_t整数、int64_t整数) -
next
:下一个节点的地址
1.3 字典
typedef struct dict {
dictType *type
void *privdata
dictht ht[2]
} dict;
-
type
:操作哈希表的各种函数 -
privdata
:上述函数所需的入参 -
ht[2]
:存储两个哈希表,一个正常使用,另一个在rehash时使用。
2. 哈希算法
- 计算哈希值 hash = dict->type->hashFunction(key);
- 计算在table数组的位置 index = hash & dict->ht[0].sizemask;
- 插入节点 创建新节点,并将其插入到table[index]的第一位。
3. rehash
3.1 何时进行rehash?
当加载因子(load factor)大于1或小于0.1时就要进行rehash。 加载因子计算公式:
load_factor = ht[0].used / ht[0].size
3.2 新哈希表大小的计算公式
当需要进行扩容/缩容的时候,究竟创建多大的哈希表呢?这取决于如下公式:
- 若要进行扩容,则新的哈希表的大小=第一个大于等于h[0].used*2的2的n次方。
- 若要进行缩容,则新的哈希表的大小=第一个大于等于h[0].used的2的n次方。
3.3 rehash过程
- 创建一个新的哈希表h[1],大小由上述公式计算得出;
- 将字典的rehashidx值从-1改为0;
- 依次遍历ht[0]上的所有节点,依次转移到ht[1]上去;
- 释放ht[0]的内存空间;
3.4 渐进式rehash
- rehash过程中需要将所有节点迁移到新的哈希表中,如果节点个数很多的情况下,迁移的过程将非常漫长,那么程序将处于停止等待状态。所以事实上,Redis的rehash过程是分多次、分布完成的。
- 在rehash过程中,每次对哈希表进行增删改查外,还要将ht[0][rehashidx]上的所有节点迁移到ht[1]中,并将rehashidx+1。从而几次操作后,ht[0]上的所有节点均被迁移至ht[1]中,rehash过程完成。
- 在rehash过程中,对哈希表的添加操作均在ht[1]上完成,ht[0]只减不增。
- JavaScript 教程
- JavaScript 编辑工具
- JavaScript 与HTML
- JavaScript 与Java
- JavaScript 数据结构
- JavaScript 基本数据类型
- JavaScript 特殊数据类型
- JavaScript 运算符
- JavaScript typeof 运算符
- JavaScript 表达式
- JavaScript 类型转换
- JavaScript 基本语法
- JavaScript 注释
- Javascript 基本处理流程
- Javascript 选择结构
- Javascript if 语句
- Javascript if 语句的嵌套
- Javascript switch 语句
- Javascript 循环结构
- Javascript 循环结构实例
- Javascript 跳转语句
- Javascript 控制语句总结
- Javascript 函数介绍
- Javascript 函数的定义
- Javascript 函数调用
- Javascript 几种特殊的函数
- JavaScript 内置函数简介
- Javascript eval() 函数
- Javascript isFinite() 函数
- Javascript isNaN() 函数
- parseInt() 与 parseFloat()
- escape() 与 unescape()
- Javascript 字符串介绍
- Javascript length属性
- javascript 字符串函数
- Javascript 日期对象简介
- Javascript 日期对象用途
- Date 对象属性和方法
- Javascript 数组是什么
- Javascript 创建数组
- Javascript 数组赋值与取值
- Javascript 数组属性和方法
- windows10在visual studio2019下配置使用openCV4.3.0
- PHP5.0 TIDY_PARSE_FILE缓冲区溢出漏洞的解决方案
- Python爬虫爬取新闻资讯案例详解
- Python代码需要缩进吗
- 解决Python paramiko 模块远程执行ssh 命令 nohup 不生效的问题
- Python计算信息熵实例
- 详解python logging日志传输
- 将tf.batch_matmul替换成tf.matmul的实现
- Python正则表达式高级使用方法汇总
- CentOS7.0下安装PHP5.6.30服务的教程详解
- Laravel Validator自定义错误返回提示消息并在前端展示
- 完美解决keras 读取多个hdf5文件进行训练的问题
- keras:model.compile损失函数的用法
- PHP获取当前系统时间的方法小结
- PHP结合jquery ajax实现上传多张图片,并限制图片大小操作示例