一文读懂Redis的dict字典数据结构( 二 )


哈希表触发扩容的时机如下:
•服务器目前没有在执行BGSAVE命令或者BGREWRITEAOF命令 , 并且哈希表的负载因子大于等于1
•服务器目前正在执行BGSAVE命令或者BGREWRITEAOF命令 , 并且哈希表的负载因子大于等于5 , 这么做的原因是避免在子进程存在期间进行哈希表扩容操作 , 从而避免不必要的内存写入操作 , 最大限度节省内存
负载因子的计算公式:

一文读懂Redis的dict字典数据结构

文章插图
 
当负载因子小于 0.1 时 , 触发缩容操作 。
渐进式rehash值得注意的是 rehash 的过程 , Redis 并不是一次性将所有元素集中式地 rehash 到 ht[1] 中 , 而是分多次 , 渐进式地完成 。
这么做的原因是如果当哈希表中存放的键值对数量如果是千万级 , 甚至亿级 , 一次性完成所有键值的 rehash 操作 , 可能会导致 Redis 一段时间内对外不可用 。
以下是渐进式 rehash 的具体步骤:
•为ht[1]分配空间 , 让字典同时持有ht[0]和ht[1]两个哈希表
•在字典中维持一个索引计数器变量rehashidx , 并将它的值设置为0 , 表示rehash工作正式开始
•在rehash进行期间 , 每次对字典执行添删改查操作时 , 程序除了执行指定的操作以外 , 还会顺带将ht[0]哈希表在rehashidx索引上的所有键值对rehash到ht[1] , 当rehash工作完成之后 , 程序将rehashidx属性的值增一
•随着字典操作的不断执行 , 最终在某个时间点上 , ht[0]的所有键值对都会被rehash至ht[1] , 这时程序将rehashidx属性的值设为-1 , 表示此次rehash操作已完成
下面展示一次完整 rehash 的过程 , 首先初始化 dict , 准备开始 rehash;
一文读懂Redis的dict字典数据结构

文章插图
 
rehashidx = 0 , rehash 索引0对应的键值对 , rehashidx + 1;
一文读懂Redis的dict字典数据结构

文章插图
 
rehashidx = 1 , rehash 索引1对应的键值对 , rehashidx + 1;
一文读懂Redis的dict字典数据结构

文章插图
 
rehashidx = 2 , rehash 索引2对应的键值对 , rehashidx + 1;
一文读懂Redis的dict字典数据结构

文章插图
 
最终完成 rehash 过程 。
一文读懂Redis的dict字典数据结构

文章插图
 




推荐阅读