哈希表节点的结构
key 键
value 值 值可以为一个指针,也可以是一个uint-64的整数,或者是一个int-64的整数。
next是指向下一个哈希节点的指针,发生键冲突的时候,采用链地址法来解决冲突,类似于Java中的hashMap。
哈希表的结构
table是一个哈希节点组成的数组
size为数组的大小
sizemask是数组的最大索引值
used为数组中已使用的(有数据的)节点的数量
以下是一个哈希表的结构
redis中字典的结构
字典类型dictType和privateData是为了实现多态类型而设置的
字典类型dictType的结构
type是指向dictType类型的指针,dictType中保存了一些用于操作指定类型键值对的函数,而private属性则保存了传给这些指定函数的可选参数。
字典和哈希表以及哈希节点的结构关系
ht是一个数组包含两个哈希表,但是只有一个是保存了数据的,另一个是空的
扩容(rehash)/ 缩容
扩容,会把空的那个哈希表大小设置为第一个大于等于used*2的2的n次方幂
缩容,会把空的那个哈希表大小设置为第一个大于等于used的2的n次方幂
扩缩容条件
负载因子:load_factor = used / size
1-当redis服务器没有执行BGSAVE或者没有执行BGREWRITEAOF命令时,且哈希表的负载因子大于等于1
2-当redis服务器正在执行BGSAVE或者正在执行BGREWRITEAOF命令时,且哈希表的负载因子大于等于5
-----因为redis采用写时复制机制来进行BGSAVE和BGREWRITEAOF,为了减少不必要的内存写入,
所以当在进行BGREWRITEAOF和BGSAVE时负载因子为更大值5
3-当负载因子小于0.1时,进行缩容
当所有数据从旧的哈希表迁移到新的哈希表后,旧的哈希表就会被清空,为下一次扩缩容做准备。
渐进式rehash
初始化ht[1]大小为扩容后的大小,使字典同时拥有两个哈希表
将rehashidx标记为0,表示rehash正式开始.在rehash期间,所有的字典增删改查操作,除了执行对应的操作外,
都会将ht[0]中rehashidx索引所对应位置上的键值对rehash到ht[1]中,当前索引位rehash完毕后会将rehashidx
的值增加一.注意,rehash期间的增加操作只会在新的哈希表ht[1]中执行,而查询删除修改则会先在ht[0]中执行,
没有得到结果再到h[1]中执行.
随着字典被不停的操作,rehash也会在某一时间点完毕,所有的键值对都将rehash到ht[1].
此时再将rehashidx置为-1,表示rehash完成.
再redis中,字典被用于数据库和hash数据结构的底层实现