首页 > 数据库 >Redis 中 hash 扩容与缩容

Redis 中 hash 扩容与缩容

时间:2022-11-10 16:33:12浏览次数:43  
标签:缩容 rehash hash Redis 哈希 dictht

Redis 中 hash 扩容与缩容 当哈希表中元素数量逐渐增加时,此时产生 hash 冲突的概率逐渐增大,且由于 dict也是采用拉链法解决 hash 冲突的,随着 hash冲突概率上升,链表会越来越长,这就会导致查找效率下降。相反,当元素不断减少时,元素占用 dict 的空间就越少,出现对于内存的极致利用,此时就需要进行缩容操作。 既然说到扩容和缩容,那就想到了负载因子。负载因子一般用于描述集合当前被填充的程度。在 Redis 的字典 dict 中,负载因子 = 哈希表中已保存节点数量 / 哈希表的大小,即: load factor = ht[0].used / ht[0].size   Redis中,三条关于扩容和缩容的规则: 1. 没有执行 BGSAVE 和 BGWRITEAOF 指令的情况下,哈希表的负载因子大于等于 1 时进行扩容。 2. 正在执行 BGSAVE 和 BGWRITEAOF 指令的情况下,哈希表的负载因子大于等于 5 时进行扩容。 3. 负载因子小于 0.1 时,Redis 自动开始对哈希表进行收索操作。   其中,扩容和缩容的数量大小也是有一定的规则: 1. 扩容:扩容后的 dicEntry 数组数量为第一个大于等于 ht[0].used * 2 的 2^n 2. 缩容:缩容后的 dicEntry 数组数量为第一个大于等于 ht[0].used 的 2^n     Redis 中 rehash 与 Java 中的 HashMap 类似,当 Redis 中的 dict 进行扩容或者缩容,会发生 reHash 过程。 Java 中 HashMap 的 rehash 过程如下:新建一个哈希表,一次性将当前所有节点进行 rehash 然后复制到新哈希表相对应的位置上,之后释放掉原有 hash 表,而持有新的表,这个过程有一个时间复杂度为 O(n) 的操作。而对于单线程的 Redis 而言很难承受这么高的时间复杂度的操作,因而其 rehash 的过程有所不同,使用一个称之为渐进式 rehash 的方式,一点一点地进行搬迁。其过程如下: 1. 假设当前数据在 dictht[0] 中,那么首先为 dictht[1] 分配足够的空间,如果是扩容,则 dictht[1] 大小就按照扩容规则设置;如果时缩减,则 dictht[1] 大小就按照缩减规则进行设置; 2. 在字典 dict 中维护一个变量,rehashidx = 0,表示 rehash 正式开始; 3. rehash 进行期间,每次对字典执行添加、删除、查找或者更新操作时,程序除了执行指定的操作以外,还会顺带将 dictht[0] 哈希表在 rehashidx 索引上的所有键值对 rehash 到 dictht[1],当一次 rehash 工作完成之后,程序将 rehashidx 属性值 +1。同时在 saveCron 中调用 rehash 相关函数,在 1ms 的时间内,进行 rehash 处理,每次仅处理少量的转移任务(100个元素); 4. 随着字典表操作的不断执行,最终在某个时间点上 dictht[0] 的所对应的键值对都会被 rehash 至 dictht[1],这时程序将 rehashidx 的属性值设置为 -1,表示 rehash 操作已完成;   redis 内有一个定时器,会定时去判断 rehash 是否完成,如果没有完成,则继续执行 rehash。从而解决上述 1,3问题,即:无访问数据如何进行rehash。 对于添加操作,会将新的数据直接添加到 dictht[1] 上面,这样就可以保证 dictht[0] 上的数量只减少不会增加。而对于删除、更新、查询操作,会执行在 dictht[0] 上进行,尤其是这三个操作,都会涉及到擦汗寻,当在 dictht[0] 上查询不到时,会接着去 dictht[1] 上查找,如果再找不到,则说明不存在该 k-v 值。   渐进式 rehash 的优缺点 优点:采用了分而治之的思想,将 rehash 操作分散到每一个对应该哈希表的操作上以及定时函数上,避免了集中式 rehash 带来的性能压力; 缺点:再 rehash 的时间内,需要保留两个 hash 表,对内存的占用稍大,而且如果在 redis 服务器本来内存满了的时候,突然进行 rehash 会造成大量的 key 被抛弃;

 

     

标签:缩容,rehash,hash,Redis,哈希,dictht
From: https://www.cnblogs.com/qiezi777/p/16877533.html

相关文章

  • SpringBoot整合Redis(十九)
    二八佳人体似酥,腰间仗剑斩愚夫。虽然不见人头落,暗里教君骨髓枯。上一章简单介绍了多数据源配置MyBatisPlus(十八),如果没有看过,​​请观看上一章​​一.Redis的介绍和安装......
  • Redis模糊匹配删除key
    在群里看到的一个Redis快速删除数据小技巧。之前我一直用scan出来再删方式,比较慢,不如本文下面这个方法。造些测试数据foriin{1..1000};doecho"setage_$i$i"|re......
  • SpringBoot整合Redis_Jedis版(二十)
    二八佳人体似酥,腰间仗剑斩愚夫。虽然不见人头落,暗里教君骨髓枯。上一章简单介绍了SpringBoot整合Redis(十九),如果没有看过,​​请观看上一章​​SpringBoot2.0版本之后,采......
  • Redis对于字符串(String)知识点理解和实操过程例子的详解记录
    一.Redis字符串1.1基本操作如果字符串内容为整数的时候。1.1.1set、mset、get、mget存和取Redis的Set是String类型的无序集合。集合成员是唯一的,这就意味......
  • Redis知识点
    Redis是一个基于内存的高性能key-value数据库Redis为了达到最快的读写速度将数据都读到内存中,并通过异步的方式将数据写入磁盘,所以Redis具有快速和数据持久化的特征,如果数......
  • Get MD5 Hash of Big Files
    RecentlyIhavebeendealingwithfilesandIneedtogetmd5hashofallkindsoffiles;Somearesmallandsomearebig.ForthesmallfilesIusethismethod......
  • 从0到1搭建redis6.0.7续更~
    “心有所向,日复一日,必有精进”前言:想必大家看完我之前写的搭建redis服务器,大家都已经把redis搭建起来了吧如果没有搭建起来的小可爱请移步这里哦从0到1搭建redis6是不是......
  • 肖sir__redis__讲解
    一、介绍数据库什么是数据库?是存放数据的电子仓库。以某种方式存储百万条,上亿条数据,供多个用户访问共享。数据库分为关系型数据库和非关系型数据库两种1,关系型数据库?......
  • Redis缓存
    认识缓存缓存更新策略缓存穿透缓存击穿缓存雪崩  认识缓存缓存的作用1,降低后端负载2,提高服务于相应速度缓存的成本1.开发成本 2,运维成本3,一致性成本......
  • Redis:哈希表HLEN、HSTRLEN、HINCRBY、HINCRBYFLOAT、HSCAN命令介绍
    HLENHLENkey时间复杂度:O(1)返回哈希表​​key​​中域的数量。演示当哈希表​​key​​不存在时,返回0。HSTRLENHSTRLENkeyfield可用版本:>=3.2.0时间复杂度:O(1)返回哈希......