Redis-哈希

哈希是Redis数据库中value的类型,它是一个键值对集合,它的存储结构有两种:压缩列表和哈希表。

经常用哈希来存储对象,比如:

 

 

(1). 当一个哈希只包含少量键值对,比且每个键值对的键和值要么就是小整数值,要么就是长度比较短的字符串,那么Redis就会使用压缩列表来做哈希的底层实现。

(2). 如果不满足哈希类型元素个数小于hash-max-ziplist-entries(默认512),所有值都小于hash-max-ziplist-value(默认64字节),则使用HashTable的底层实现。

跟哈希有关的三个结构:

 

 

从左到右是:a). 哈希表 b).哈希表结点 c).字典

我们的数据封装成哈希表结点放在哈希表内的数组中,而我们所使用的哈希结构是最右边那个。值得注意的是,它里面有两个哈希表,其中一个是用来存放数据的,另一个是用来扩容用的。

扩容算法:

当服务器目前没有在进行持久化操作时,并且哈希表的负载因子大于等于1。或者当服务器正在执行持久化操作,并且哈希表的负载因子大于等于5。会触发扩容。

步骤为:

(1). 给字典的ht[1]哈希表分配空间,它的大小为第一个大于等于ht[0].used*2的2n

(2). 将ht[0]中的所有键值对rehash到ht[1]上。

(3). 将所有键值对都迁移到ht[1]上之后,释放ht[0],然后将ht[1]设置为ht[0],并在ht[1]新创建一个空白哈希表,为下一次扩容做准备。

上面步骤中的第(2)步使用的是:渐进式rehash

使用渐进式rehash的原因是,如果ht[0]中只保存着四个键值对,那么rehash的过程会很快,但是,如果哈希表里保存的键值对数量很多,那么一次性将全部键值对rehash到ht[1]中会导致服务器在一段时间内停止服务。所以,为了避免rehash对服务器性能造成影响,服务器将分多次、渐进式地将ht[0]里面的键值对rehash到ht[1]。

渐进式rehash的详细步骤为:

(1). 为ht[1]分配空间,让字典同时持有ht[0]和ht[1]。即给ht[1]分配大小为第一个大于ht[0].used*2的2n的哈希表。

(2). 在字典中维持一个索引计数器变量rehashidx,初值为0,表示rehash正式开始。

(3). 在rehash进行期间,每次对字典执行增删改查操作时,程序除了执行指定的操作外,还会顺带将ht[0]哈希表在rehashidx索引上的所有键值对rehash到ht[1],当该索引上所有键值对rehash完成后,程序将rehashidx属性的值加1。

(4). 随着字典操作的不断执行,最终在某个时间点上,ht[0]的所有键值对都被rehash到ht[1],此时程序将rehashidx属性值设置为-1,表示rehash完成。

总结:渐进式rehash的过程就是,每次执行增删改查时,执行一次rehash,最终将ht[0]上的所有键值对都rehash到ht[1]上,避免了集中式rehash带来的庞大计算量。

结尾:如果在rehash过程中,执行增删改查操作,会同时在两个哈希表上进行。

posted @ 2021-10-18 21:07  妞是人间四月天  阅读(107)  评论(0)    收藏  举报