哈希表触发扩容的时机如下:
•服务器目前没有在执行BGSAVE命令或者BGREWRITEAOF命令 , 并且哈希表的负载因子大于等于1
•服务器目前正在执行BGSAVE命令或者BGREWRITEAOF命令 , 并且哈希表的负载因子大于等于5 , 这么做的原因是避免在子进程存在期间进行哈希表扩容操作 , 从而避免不必要的内存写入操作 , 最大限度节省内存
负载因子的计算公式:
文章插图
当负载因子小于 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;
文章插图
rehashidx = 0 , rehash 索引0对应的键值对 , rehashidx + 1;
文章插图
rehashidx = 1 , rehash 索引1对应的键值对 , rehashidx + 1;
文章插图
rehashidx = 2 , rehash 索引2对应的键值对 , rehashidx + 1;
文章插图
最终完成 rehash 过程 。
文章插图
推荐阅读
- 新疆维吾尔自治区|一文带你了解和田玉“前世今生”
- Go语言 连接池相关总结:HTTP、RPC、Redis 和数据库等
- 谈谈 Redis 的过期策略
- 五大实例详解,携程 Redis 跨机房双向同步实践
- 5 款超好用的数据库 GUI 带你玩转 MongoDB、Redis、SQL 数据库
- 三分钟快速搭建分布式高可用的Redis集群
- 在Redis中进行分页排序查询
- HDMI 2.0已淘汰!HDMI 2.1上位:一文看懂新接口优势
- 索尼|PS5存储扩容需要注意啥?一文读懂
- 一文读懂AI计算机视觉技术