Redisbook学习笔记(1)字典(2)
添加新元素到空白字典
当第一次往空字典里添加键值对时,程序会根据dict.h/DICT_HT_INITIAL_SIZE 里指定的大
小为d->ht[0]->table 分配空间(在目前的版本中,DICT_HT_INITIAL_SIZE 的值为4 )。
以下是字典空白时的样子:
以下是往空白字典添加了第一个键值对之后的样子:
添加新键值对时发生碰撞处理
在哈希表实现中,当两个不同的键拥有相同的哈希值时,我们称这两个键发生碰撞(collision),
而哈希表实现必须想办法对碰撞进行处理。
字典哈希表所使用的碰撞解决方法被称之为链地址法:这种方法使用链表将多个哈希值相同的
节点串连在一起,从而解决冲突问题。
假设现在有一个带有三个节点的哈希表,如下图:
对于一个新的键值对key4 和value4 ,如果key4 的哈希值和key1 的哈希值相同,那么它们
将在哈希表的0 号索引上发生碰撞。
通过将key4-value4 和key1-value1 两个键值对用链表连接起来,就可以解决碰撞的问题:
添加新键值对时触发了rehash 操作
对于使用链地址法来解决碰撞问题的哈希表dictht 来说,哈希表的性能依赖于它的大小(size
属性)和它所保存的节点的数量(used 属性)之间的比率:
比率在1:1 时,哈希表的性能最好;
如果节点数量比哈希表的大小要大很多的话,那么哈希表就会退化成多个链表,哈希表
本身的性能优势就不再存在;
举个例子,对于下面这个哈希表,平均每次失败查找只需要访问1 个节点(非空节点访问2
次,空节点访问1 次):
而对于下面这个哈希表,平均每次失败查找需要访问5 个节点:
为了在字典的键值对不断增多的情况下保持良好的性能,字典需要对所使用的哈希表(ht[0])
进行rehash 操作:在不修改任何键值对的情况下,对哈希表进行扩容,尽量将比率维持在1:1
左右。
dictAdd 在每次向字典添加新键值对之前,都会对哈希表ht[0] 进行检查,对于ht[0] 的
size 和used 属性,如果它们之间的比率ratio = used / size 满足以下任何一个条件的话,
rehash 过程就会被激活:
1. 自然rehash :ratio >= 1 ,且变量dict_can_resize 为真。
2. 强制rehash : ratio 大于变量dict_force_resize_ratio (目前版本中,
dict_force_resize_ratio 的值为5 )。
Note: 什么时候dict_can_resize 会为假?
在前面介绍字典的应用时也说到过,一个数据库就是一个字典,数据库里的哈希类型键
也是一个字典,当Redis 使用子进程对数据库执行后台持久化任务时(比如执行BGSAVE
或BGREWRITEAOF 时), 为了最大化地利用系统的copy on write 机制, 程序会暂时将
dict_can_resize 设为假,避免执行自然rehash ,从而减少程序对内存的触碰(touch)。
当持久化任务完成之后,dict_can_resize 会重新被设为真。
另一方面,当字典满足了强制rehash 的条件时,即使dict_can_resize 不为真(有BGSAVE
或BGREWRITEAOF 正在执行),这个字典一样会被rehash 。
Rehash 执行过程
字典的rehash 操作实际上就是执行以下任务:
1. 创建一个比ht[0]->table 更大的ht[1]->table ;
2. 将ht[0]->table 中的所有键值对迁移到ht[1]->table ;
3. 将原有ht[0] 的数据清空,并将ht[1] 替换为新的ht[0] ;
经过以上步骤之后,程序就在不改变原有键值对数据的基础上,增大了哈希表的大小。
作为例子,以下四个小节展示了一次对哈希表进行rehash 的完整过程。
1. 开始rehash
这个阶段有两个事情要做:
1. 设置字典的rehashidx 为0 ,标识着rehash 的开始;
2. 为ht[1]->table 分配空间,大小至少为ht[0]->used 的两倍;
这时的字典是这个样子:
Rehash 进行中
在这个阶段,ht[0]->table 的节点会被逐渐迁移到ht[1]->table ,因为rehash 是分多次进
行的(细节在下一节解释),字典的rehashidx 变量会记录rehash 进行到ht[0] 的哪个索引
位置上。
以下是rehashidx 值为2 时,字典的样子:
注意除了节点的移动外,字典的rehashidx 、ht[0]->used 和ht[1]->used 三个属性也产生
了变化。
3. 节点迁移完毕
到了这个阶段,所有的节点都已经从ht[0] 迁移到ht[1] 了:
4. Rehash 完毕
在rehash 的最后阶段,程序会执行以下工作:
1. 释放ht[0] 的空间;
2. 用ht[1] 来代替ht[0] ,使原来的ht[1] 成为新的ht[0] ;
3. 创建一个新的空哈希表,并将它设置为ht[1] ;
4. 将字典的rehashidx 属性设置为-1 ,标识rehash 已停止;
以下是字典rehash 完毕之后的样子:
对比字典rehash 之前和rehash 之后,新的ht[0] 空间更大,并且字典原有的键值对也没有被
修改或者删除。
转载于:https://blog.51cto.com/janephp/1353526
Redisbook学习笔记(1)字典(2)相关推荐
- Python学习笔记:字典(dict)
Python学习笔记:字典(dict) 字典(dict)可能是最重要的Python内置数据结构,更常用的名称是哈希映射(hash map)或关联数组(associate array).它是键值对的集合 ...
- 【安全牛学习笔记】字典、在线密码破解-hydra
字典 按个人信息生成其专属的密码字典 CUPP: Common User Password Profiler - git clone https://github.com/Mebus/cupp.git ...
- Object C学习笔记13-Dictionary字典
通过Array数组和Set集合的学习和理解,可以想象得到Dictionary也分为两种情况了,那就是可变和不可变两种类型的.的确如此,在Object C中提供了两个字典类,分别为NSDictionar ...
- Python学习笔记之字典(三)
嵌套:有时候,需要将一系列字典存储在列表中,或将列表作为值存储在字典中,这称为嵌套.你可以在列表中嵌套字典.在字典中嵌套列表甚至在字典中嵌套字典. 1.字典列表,一个列表里面包含多个字典,即列表中嵌套 ...
- Python学习笔记之字典(二)
遍历字典:一个Python字典可能包含很多个键值对,在需要获取其数据时,就需要对这个进行遍历,Python支持对字典遍历.字典可用于以各种方式存储信息,其中有多种遍历字典的方式:可遍历字典的所有键值对 ...
- Python学习笔记之字典(一)
1.什么是字典:在Python中,字典是一系列键-值对.每个键都与一个值相关联,你可以使用键来访问与之相关联的值.与键相关联的值可以是数字.字符串.列表乃至字典.事实上,可将任何Python对象用作字 ...
- 初学Python的学习笔记2----dist字典,set集合,声明函数,函数参数
2019独角兽企业重金招聘Python工程师标准>>> 7. dist(字典--键值对)d = {'Michael': 95, 'Bob': 75, 'Tracy': 85}---& ...
- Redisbook学习笔记(1)跳跃表
一个典型的跳跃表例子 从图中可以看到,跳跃表主要由以下部分构成: 表头(head):负责维护跳跃表的节点指针. 跳跃表节点:保存着元素值,以及多个层. 层:保存着指向其他元素的指针.高层的指针越过 ...
- Redisbook学习笔记(3)数据类型之对象处理机制
在Redis 的命令中,用于对键(key)进行处理的命令占了很大一部分,而对于键所保存的值的 类型(后简称"键的类型" ),键能执行的命令又各不相同. 比如说,LPUSH 和LLE ...
最新文章
- 两条线段相切弧_两条直线间的圆弧连接
- linux如何连接移动硬盘
- Unity之流光效果
- 控制用户的访问之权限、角色【weber出品必属精品】
- 【服务端渲染】NuxtJs 综合案例
- 2020年二级计算机考试真题,2020年3月计算机等级考试《二级MS Office高级应用》历年真题-试题答案...
- 人生永无止境的意思是什么_人生追求永无止境名言
- BZOJ 2226 [Spoj 5971] LCMSum 最大公约数之和 | 数论
- 【Java TCP/IP Socket】应用程序协议中消息的成帧与解析(含代码)
- Python基本知识
- 一款基于jQuery可放大预览的图片滑块插件
- MOS驱动电路设计需要注意的地方
- java健身房管理系统业务_基于SSM的健身房管理系统
- 泥瓦匠之 Java 的成长感悟
- 安装部署(七) HBase集群安装部署与测试
- Linux系统cut命令详解
- Docker配置DaoCloud加速器镜像
- 微信api调用限制,45009 reach max api daily quota limit 解决方法
- Apache Doris 0.11.x 版本升级
- 欧洲央行目前已完成数字欧元公众咨询
热门文章
- 浙江独立学院计算机专业排名2015,2014-2015年中国独立学院排名
- access转sql iif_ACCESS 中的IIF使用
- python 获取网页元素_记一次python提取网页标签元素的坑
- python程序怎样在手机上_python手机文件怎么上传至电脑?
- 特征级融合_多知识图谱的融合算法探索
- python画图颜色代码_Python-使用matplotlib创建自己的颜色图并绘制颜色比例
- java bundle类_java ResourceBundle介绍
- eventlistener java_EventListener原理
- python 3.7.4 shell_centos7上Virtualenv从python3.4升级到Python3.7.4
- win10 安装db2 10.1 并使用DBserver连接db2数据库