当前位置: 首页 > news >正文

Redis原理:为什么要rehash

在 Redis的数据结构(一),有提到Redis的dict结构中,有两个dictEntry的数组

之前只是提到,它是作为rehash时使用的,那为什么需要rehash呢?

Redis是作为一个字典表存在的,它是基于hash表进行查找数据的

那它的查找方式基于以下的步骤

  1. 通过hash算法,获取在当前hash表中的位置,时间复杂度 O(1)
  2. 如果有hash冲突,则遍历当前的位置的各个dictEntry,比对相应的值,时间复杂度为 O(N)

为什么会有O(N)的出现呢,因为hash算法会存在hash碰撞,当出现hash碰撞时,redis 通过使用链表的方式来存储对应的键值,如果熟悉Java中的HashMap的算法,其中的原理是类似的。

那要解决的问题,主要是尽量使hash 碰撞的概率减小,解决方案便是进行hash表的扩容。而上面提到的两个ht_table表就是为了在扩容或是缩容时使用的。来看下具体的源码

  1. rehash 的过程是从ht_table[0]中,按索引的位置,将该bucket中的列表逐个迁移到ht_table[1]中,这也是为了防止在迁移过程中长时间的阻塞导致redis不可用,并不是一次性进行迁移的,而是渐进式的
  2. 更新ht_table[0] 的 rehashidx的值
  3. 在ht_table[0]迁移完成后,会释放ht_table[0],同时重新将ht_table[1] 设置为 ht_table[0]

既然在rehash的过程,会将数据分散在两个表中,那在查找、新增、删除时是如何处理呢?来看下获取对应key的过程

这里会分别在两个ht_table中进行查找。

而新增呢?

从以上逻辑可以知道,当在插入时,只会插入到ht_table[1]中。

既然 rehash 是为了解决hash冲突的问题,那什么时候会触发呢?

在上面的流程里,有调用 _dictExpandIfNeeded 方法

这里可以总结下扩容的时机点:

  1. 未初始化,会进行初始化第一个ht_table
  2. 当key的总数大于hashtable的大小,接近1:1 时,并且 dict_can_resize为1 或是 负载因子大于5时
  3. 扩容规则是找到大于当前key的总数的最小2的指数倍
  4. 扩容以后,会将dict中的rehashidx的值会被置为0

扩容以后,后台线程(1秒钟执行10次)检查是否在扩容后,需要rehash,如果需要,则会调用以下的方法

或是新增、删除key时判断是需要rehash,之后会调用 _dictRehashStep进行迁移一个bucket

总结

Redis的rehash 是为了解决hash冲突带来的性能问题,将原来紧凑的数据分布,进行松散分布,可以使key的查找尽可能达到O(1)

相关文章:

  • 详细分析HttpClient的基本知识(附Demo实战思路)
  • SEV内存加密位linux内核设置过程
  • C++锁: 读锁,递归锁,超时锁
  • 2025系统分析师---软件工程:深度剖析常见软件开发方法
  • Nature Machine Intelligence 嵌入式大语言模型使机器人能够在不可预测的环境中完成复杂的任务
  • WordPress WooCommerce 本地文件包含漏洞(CVE-2025-1661)
  • 网络编程基础知识——从基础到实操
  • 常见框架漏洞(一)----Thinkphp(TP)
  • Android之卡片式滑动
  • 零基础上手Python数据分析 (9):DataFrame 数据读取与写入 - 让数据自由穿梭
  • 基于Java的班级事务管理系统(源码+lw+部署文档+讲解),源码可白嫖!
  • HarmonyOS-ArkUI Grip组件
  • Charles汉化步骤 charles中文版怎么用
  • 凝视型高光谱相机:钻石光谱分析研究与应用
  • PoE交换机如何助力智慧城市基础设施建设?
  • C# 如何检查给定的四个点是否形成一个正方形(How to check if given four points form a square)
  • docker ssh远程连接
  • uni app跨端开发遇到的问题
  • Linux搭建本地时间服务器及时间同步
  • mysql中show命令的使用
  • 福建住建设厅官方网站/百度关键词代做排名
  • 东港网站建设/百度指数的搜索指数
  • 家具网站开发任务书/外贸网站哪个比较好
  • 网站域名怎么做变更/太原互联网推广公司
  • 广告公司网站模版/网页制作教程步骤
  • 主题教育网站建立/竞价推广招聘