Redis渐进式rehash小疑问
一、rehash是什么
在Redis中,Rehash是指在进行哈希表扩容或缩容时重新计算和重新分配哈希槽的过程。Redis使用哈希表来存储键值对,哈希表中的每个槽位对应一个哈希槽,每个槽位可以存储多个键值对。 当哈希表的负载因子(load factor)超过一定阈值时,Redis会触发Rehash操作来扩容哈希表,以提供更多的槽位来存储新的键值对。Rehash的过程如下:
- 创建新哈希表:在扩容之前,Redis会创建一个新的空哈希表,大小是原始哈希表的两倍。新哈希表中的槽位只有一小部分被使用,其他槽位为空。
- 迁移数据:Redis会从原始哈希表中逐个遍历槽位,将其中的数据逐步迁移到新哈希表中。每次迁移一个槽位的数据。
- 增量迁移:在迁移数据的过程中,Redis会将新写入的数据直接存储在新哈希表中。这样可以避免在迁移期间对原始哈希表进行频繁的写入操作。
- 并发访问:在渐进式rehash期间,Redis会同时维护原始哈希表和新哈希表。每次访问哈希表时,Redis会同时在两个哈希表中查找数据,以保证数据的一致性。这样可以避免数据丢失或不一致的情况。
- 迁移完成:当所有数据都成功迁移到新哈希表中后,渐进式rehash过程完成。此时,Redis会将新哈希表设置为当前的活动哈希表,原始哈希表不再使用,最终会被释放掉
在Rehash过程中,Redis会逐步将原来哈希表中的键值对迁移到新的哈希表中,直到所有键值对都迁移完成。在这个过程中,Redis仍然可以处理客户端的读写请求,但可能会有一些额外的CPU和内存消耗。 Rehash操作是在后台进行的,不会阻塞Redis的正常操作。在Rehash过程中,如果有新的写操作发生,Redis会同时将新的键值对写入原来的哈希表和新的哈希表中,以保证数据的一致性。 需要注意的是,Rehash操作可能会导致Redis的内存使用量短暂地增加,因为在Rehash过程中同时存在原来的哈希表和新的哈希表。一旦Rehash完成,Redis会释放原来哈希表的内存空间。 总结起来,Redis的Rehash是指在哈希表扩容或缩容时重新计算和重新分配哈希槽的过程,用于提供更多或更少的槽位来存储键值对。Rehash操作是在后台进行的,不会阻塞Redis的正常操作。
二、疑问
2.1 新哈希槽和原始哈希槽中的key是如何对应的
解答:在渐进式rehash算法中,新哈希槽和原始哈希槽中的key是通过哈希函数计算得出的哈希值来进行对应的。 具体的对应过程如下:
- 原始哈希槽:初始时,所有的key都存储在原始哈希槽中。每个key通过哈希函数计算出一个哈希值,然后根据哈希值对应到原始哈希槽的一个位置。
- 新哈希槽:在进行渐进式rehash时,会逐步创建新的哈希槽。新哈希槽的大小通常是原始哈希槽的两倍。同样,每个key也通过哈希函数计算出一个哈希值,然后根据哈希值对应到新哈希槽的一个位置。
- 数据迁移:在渐进式rehash过程中,会逐步将原始哈希槽中的key迁移到新哈希槽中。当需要进行数据迁移时,会根据每个key的哈希值,确定其在新哈希槽中的位置,并将其从原始哈希槽移动到新哈希槽的相应位置。
- 对应关系:通过哈希函数计算出的哈希值,决定了每个key在原始哈希槽和新哈希槽中的位置。当进行数据访问时,会根据key的哈希值,确定其在原始哈希槽或新哈希槽中的位置,从而找到对应的数据。
需要注意的是,在渐进式rehash过程中,可能会存在一段时间内同时存在原始哈希槽和新哈希槽中的key。这是为了确保数据的平滑迁移和一致性。随着数据的迁移完成,最终所有的key都会在新哈希槽中找到对应的位置。
2.2 如果同时存在原始哈希槽和新哈希槽中的key,并发访问时如何选择呢
解答:在同时存在原始哈希槽和新哈希槽的情况下,并发访问可能会同时访问到新哈希槽和原始哈希槽中的key。在这种情况下,具体的选择取决于系统的实现和算法。
数据迁移策略:
- 逐步迁移:可以逐步将原始哈希槽中的数据迁移到新哈希槽中,直到所有数据都迁移完成。可以根据系统负载和性能需求,控制迁移速度和并发度。
- 批量迁移:可以将原始哈希槽中的数据批量迁移到新哈希槽中,以减少迁移的次数和开销。可以根据系统的负载和数据量,设置合适的批量大小。
访问优先级规则:
- 优先访问新哈希槽:可以设置优先访问新哈希槽中的数据,以加快新数据的访问速度。可以根据业务需求和数据迁移的进度,调整访问优先级规则。
- 均衡访问:可以平均分配访问请求到原始哈希槽和新哈希槽中,以保持整体的负载均衡。可以根据系统的负载情况和性能需求,调整访问均衡策略。
同时,在渐进式rehash期间,Redis Cluster会执行以下并发控制机制:
- 数据迁移:当进行数据迁移时,Redis Cluster会确保在迁移过程中数据的一致性。它使用了一种类似于2PC(两阶段提交)的机制来保证迁移的原子性和一致性。迁移过程中,源节点和目标节点会进行协同操作,确保数据的正确迁移和复制。这样可以避免数据丢失或重复复制的问题。
- 槽分配:在渐进式rehash期间,Redis Cluster会动态调整数据槽的分配。它使用了一种基于Gossip协议的分布式一致性算法,通过节点之间的通信和协商,确保数据槽的分配在整个集群中保持一致。这样可以避免数据丢失或重复复制的问题,并保证数据的一致性。
- 客户端路由:在渐进式rehash期间,Redis Cluster会根据槽分配的变化,调整客户端的路由策略。客户端会根据新的槽分配信息,将请求发送到正确的节点上。这样可以确保客户端的请求在整个rehash过程中都能正确地访问到数据,并保持一致性。
2.3. 假设是在rehash过程中删除某个key呢?会怎么样操作
解答:如果要删除某个key,渐进式rehash算法并不会对此产生影响。删除操作不需要进行数据迁移,因此可以直接在原始哈希表中执行删除操作,而不涉及新哈希表。 具体的删除操作如下:
- 在原始哈希表中查找要删除的key。
- 如果找到了该key,直接删除它。
- 如果没有找到该key,说明它可能已经被迁移到新哈希表中,此时需要在新哈希表中查找并删除。
在删除操作中,渐进式rehash算法会同时维护原始哈希表和新哈希表,以确保数据的一致性。删除操作可以在两个哈希表中进行查找和删除,以保证数据的正确性。 需要注意的是,删除操作可能会导致哈希表的负载不均衡。如果删除操作频繁且集中在某个区域,可能会导致哈希表的负载不均衡,需要根据实际情况进行调整和优化,以确保系统的性能和可用性。
2.4 上面说了,迁移过程中,可能会存在一段时间内同时存在原始哈希槽和新哈希槽中的key,假设对某个key的值进行修改,新哈希槽和旧哈希槽的值都会改变吗
解答:在Redis Cluster的迁移过程中,如果对某个key的值进行修改,新哈希槽和旧哈希槽的值都可能会发生改变。这是因为迁移过程中,Redis Cluster会根据新的槽分配信息将数据从旧节点迁移到新节点,同时更新相关的哈希槽信息。 具体来说,如果对某个key的值进行修改,可能会发生以下情况:
- 如果key的哈希槽在迁移过程中仍然属于旧节点的范围内,那么修改操作会在旧节点上进行,并且新节点的哈希槽信息不会改变。
- 如果key的哈希槽在迁移过程中已经被迁移到新节点,那么修改操作会在新节点上进行,并且新节点的哈希槽信息会更新。
在任何情况下,Redis Cluster会确保数据的一致性和可用性。如果在迁移过程中对某个key的值进行修改,Redis Cluster会根据哈希槽信息将修改操作正确地路由到相应的节点上,以保证数据的正确性。
2.5 如果在一段时间内旧节点和新节点都存在相同的数据副本,并且访问优先级规则是均衡的,那不就出现两次访问数据不一致了吗
解答:如果一个客户端在迁移过程中先访问了旧节点,然后再访问了新节点,确实会导致数据不一致的情况,因为旧节点和新节点上的数据副本可能不同步。 为了解决这个问题,Redis Cluster引入了客户端的重定向机制。当客户端请求到达一个旧节点,而该节点的数据已经迁移到了新节点时,旧节点会返回一个MOVED重定向错误,指示客户端重新发送请求到新节点。这样可以确保客户端的请求始终路由到正确的节点上,保证数据的一致性。 此外,Redis Cluster还提供了ASK重定向机制,用于处理正在进行迁移的哈希槽。ASK重定向机制类似于MOVED,但会告诉客户端该哈希槽正在迁移中,客户端可以根据ASK重定向错误重新发送请求到新节点。 综上所述,虽然在迁移过程中可能存在一段时间内旧节点和新节点都存在相同的数据副本,但通过Redis Cluster的重定向机制,可以确保客户端的请求始终路由到正确的节点上,避免数据不一致的问题。
2.6 重试case
客户端需要手动实现一个重定向处理器,并需要考虑以下几点:
- 重试次数限制:为了避免无限重试,可以设置一个重试次数限制,超过限制后可以选择放弃请求或进行其他处理。
- 错误处理策略:除了重试,还可以根据具体的业务需求,选择其他错误处理策略,例如记录日志、回滚操作等。
- 高可用性和容错性:为了提高系统的高可用性和容错性,可以在客户端实现多个节点的故障转移和自动重试,以应对节点故障和重定向错误。
例如,使用Redisson来实现:Redisson重定向默认限制为16次,若超出,会抛出 RedisConnectionException
异常,指示重定向次数过多
import org.redisson.Redisson;
import org.redisson.api.*;
import org.redisson.api.exception.RedissonMovedException;
import org.redisson.api.exception.RedissonAskException;public class RedissonClusterExample {public static void main(String[] args) {Config config = new Config();config.useClusterServers().addNodeAddress("redis://127.0.0.1:7000", "redis://127.0.0.1:7001").setRedirectionHandler(new RedissonRedirectionHandler() {@Overridepublic void handle(String host, int port, RedisMovedException e) {// 处理MovedDataExceptionSystem.out.println("Handling MovedDataException");// 更新Redisson配置以连接到新的节点config.useClusterServers().addNodeAddress("redis://" + host + ":" + port);}@Overridepublic void handle(String host, int port, RedisAskException e) {// 处理AskDataExceptionSystem.out.println("Handling AskDataException");// 更新Redisson配置以连接到新的节点config.useClusterServers().addNodeAddress("redis://" + host + ":" + port);}});RedissonClient redisson = Redisson.create(config);RMap<String, String> map = redisson.getMap("myMap");map.put("key", "value");redisson.shutdown();}
}
相关文章:

Redis渐进式rehash小疑问
一、rehash是什么 在Redis中,Rehash是指在进行哈希表扩容或缩容时重新计算和重新分配哈希槽的过程。Redis使用哈希表来存储键值对,哈希表中的每个槽位对应一个哈希槽,每个槽位可以存储多个键值对。 当哈希表的负载因子(load facto…...

C#winform门诊医生系统+sqlserver
C#winform门诊医生系统sqlserver说明文档 运行前附加数据库.mdf(或sql生成数据库) 主要技术:基于C#winform架构和sql server数据库 功能模块: 个人中心:修改个人信息、打开照片并进行修改 预约挂号:二级…...

设计模式 -- 工厂模式(Factory Pattern)
工厂模式:属于 创建型模 式,最常用的设计模式之一,提供了一种创建对象的最佳方式。 介绍 意图:定义一个创建对象的接口,让其子类自己决定实例化哪一个工厂类,工厂模式使其创建过程延迟到子类进行。主要解决…...

设计模式-08-适配器模式
经典的设计模式有23种,但是常用的设计模式一般情况下不会到一半,我们就针对一些常用的设计模式进行一些详细的讲解和分析,方便大家更加容易理解和使用设计模式。 1-适配器模式原理 适配器模式的英文翻译是Adapter Design Pattern。顾名思义&…...

北邮22级信通院数电:Verilog-FPGA(9)第九周实验(4)实现寄存器74LS374
北邮22信通一枚~ 跟随课程进度更新北邮信通院数字系统设计的笔记、代码和文章 持续关注作者 迎接数电实验学习~ 获取更多文章,请访问专栏: 北邮22级信通院数电实验_青山如墨雨如画的博客-CSDN博客 目录 一.代码部分 1.1 reg_74LS374.v 1.2 reg_LS3…...

【Android】带下划线的TextView
序言 我们有时候需要一个类似这样的显示,上面是文字,下面是一条线 这样的显示效果是TextView实现不了的,需要我们自己进行修改一下。 实现 创建一个UnderlineTextView,继承系统的TextView class UnderlineTextView(mContext…...

图解未来:数据可视化引领智慧决策时代
图表和数据可视化在数据分析中的关键作用 引言: 在现代数据科学中,数据可视化扮演着至关重要的角色。通过图表和可视化工具,我们能够更直观、更有效地理解数据的分布、趋势和关联性。本文将深入讨论三个主要的数据可视化工具:mat…...

例解什么是Python装饰器
Python中的装饰器一直是一个比较难理解的概念,我自己理解的就是用一个函数去修改另一个函数,主要是为另一个函数添加计时等功能,而且不用改变另一个函数,这样就大大减少了另一个函数的维护成本。 这个装饰器,英文名就…...

EtherCAT从站EEPROM组成信息详解(3):字16-63邮箱、EEPROM信息
0 工具准备 1.EtherCAT从站EEPROM数据(本文使用DE3E-556步进电机驱动器)1 字10-63邮箱、EEPROM信息 1.1 字10-63组成规范 字10-63虽然包含的空间区域很大,但实际上仅包含引导状态下邮箱配置、标准邮箱配置、EEPROM大小、执行的SII标准版本…...

【文件读取/包含】任意文件读取漏洞 afr_1
1.1漏洞描述 漏洞名称任意文件读取漏洞 afr_1漏洞类型文件读取漏洞等级⭐漏洞环境docker攻击方式 1.2漏洞等级 高危 1.3影响版本 暂无 1.4漏洞复现 1.4.1.基础环境 靶场docker工具BurpSuite 1.4.2.靶场搭建 1.创建docker-compose.yml文件 version: 3.2 services: web: …...

(八)五种元启发算法(DBO、LO、SWO、COA、LSO、KOA、GRO)求解无人机路径规划MATLAB
一、五种算法(DBO、LO、SWO、COA、GRO)简介 1、蜣螂优化算法DBO 蜣螂优化算法(Dung beetle optimizer,DBO)由Jiankai Xue和Bo Shen于2022年提出,该算法主要受蜣螂的滚球、跳舞、觅食、偷窃和繁殖行为…...

通义灵码,阿里巴巴的编程辅助工具
一、官网 通义灵码_智能编码助手_AI编程_人工智能-阿里云 二、安装VSCode 如何下载安装VSCode 三、VSCode安装通义灵码 1.访问扩展详情界面 方式1 访问通义灵码安装教程页面 方法2 访问VSCode市场中的TONGYI Lingma 点击 Install 按钮访问扩展详情界面 2.打开VSCode …...

Uniapp导出的iOS应用上架详解
目录 Uniapp导出的iOS应用上架详解 摘要 引言 苹果审核标准 苹果调试 注意事项和建议 总结 摘要 本文将探讨Uniapp导出的iOS应用能否成功上架的问题。我们将从苹果审核标准、性能影响、调试流程等多个方面进行深入分析,以及向开发者提供相关注意事项和建议。…...

计算机视觉基础(7)——相机基础
前言 从这一节开始,我们来学习几何视觉。中层视觉包括相机模型、单目几何视觉、对极几何视觉和多目立体视觉等。在学习几何视觉最开始,我们先来学习一下相机模型,了解相机的基本原理,了解相机如何记录影像。 一、数字相机 1.1 基…...

解决Github上的README无法显示图片
首先感谢博主的思路:思路 最近写了点东西提交到git 发现本地能查看md里的图片用的相对路径,提交到github就看不见,并且发现不只是我自己的仓库看不见,其他人的我也看不见。那就有问题了 解决:正常使用相对路径&…...

qnx 工程目录创建工具 addvariant
文章目录 前言一、addvariant 是什么二、addvariant 使用实例1. variant names 参数说明2. 创建一个可执行文件工程3. 创建一个动态库工程 总结参考资料 前言 本文主要介绍如何在qnx 开发环境中创建工程目录及其相关的配置文件(common.mk, Makefile 文件等) 软件版本ÿ…...

计算机视觉+深度学习+机器学习+opencv+目标检测跟踪+一站式学习(代码+视频+PPT)
第1章:视觉项目资料介绍与学习指南 相关知识: 介绍计算机视觉、OpenCV库,以及课程的整体结构。学习概要: 了解课程的目标和学习路径,为后续章节做好准备。重要性: 提供学生对整个课程的整体认识࿰…...

【AI视野·今日CV 计算机视觉论文速览 第278期】Mon, 30 Oct 2023
AI视野今日CS.CV 计算机视觉论文速览 Mon, 30 Oct 2023 Totally 50 papers 👉上期速览✈更多精彩请移步主页 Daily Computer Vision Papers Image Clustering Conditioned on Text Criteria Authors Sehyun Kwon, Jaeseung Park, Minkyu Kim, Jaewoong Cho, Ernest…...

深度学习:多模态与跨模态
1 定义 1.1 多模态学习 多模态学习(Multimodal Learning)是一种利用来自多种不同感官或交互方式的数据进行学习的方法。在这个语境中,“模态”指的是不同类型的数据输入,如文本、图像、声音、视频等。多模态学习的关键在于整合和…...

大数据Hadoop之——部署hadoop+hive+Mysql环境(Linux)
目录 一、JDK的安装 1、安装jdk 2、配置Java环境变量 3、加载环境变量 4、进行校验 二、hadoop的集群搭建 1、hadoop的下载安装 2、配置文件设置 2.1. 配置 hadoop-env.sh 2.2. 配置 core-site.xml 2.3. 配置hdfs-site.xml 2.4. 配置 yarn-site.xml 2.5. 配置 ma…...

Python与ArcGIS系列(四)在地图文档中加入图层
目录 0 简述1 将图层添加到地图文档中2 将图层插入到地图文档0 简述 本篇介绍如何利用arcpy实现将图层添加到地图文档中,以及将图层插入到地图文档指定的位置。 1 将图层添加到地图文档中 arcpy的mapping模块提供的AddLayer()函数可以实现将图层添加到地图文档中。功能本质上…...

QT 程序异常崩溃
出现以下问题,大概率是你在修改代码时,在pro或者pri中增加了一些不存在的头文件或者cpp,使用BeyondCmp仔细对比,分享,希望帮助到你...

Ubuntu20.04 通过nmcli命令查看网卡状态为unmanaged
问题描述: 通过下述指令查看网卡状态为 "unmanaged" nmcli dev status 解决方法: cd /usr/lib/NetworkManager/conf.d/ sudo mv 10-globally-managed-devices.conf 10-globally-managed-devices.conf.bak sudo cp 10-globally-managed-devic…...

【R Error系列】r - fatal error : RcppEigen. h:没有这样的文件或目录
在头文件那要有 // [[Rcpp::depends(RcppEigen)]] 即: #include <Rcpp.h> #include <RcppEigen.h> using namespace Rcpp; using namespace Eigen;// [[Rcpp::depends(RcppEigen)]] // [[Rcpp::export]] 参考: r - fatal error: RcppEi…...

如何在聊天记录中实时查找大量的微信群二维码
10-5 如果你有需要从微信里收到的大量信息中实时找到别人发到群里的二维码,那本文非常适合你阅读,因为本文的教程,可以让你在海量的微信消息中,实时地把二维码自动挑出来,并且帮你分类保存。 如果你是做网推的&#…...

03-CSS基础选择器
3.1 CSS基础认知🍎 3.1.1 👁️🗨️CSS概念 CSS:层叠样式表(Cascading style sheets),为网页标签增加样式表现的 语法格式: 选择器{<!-- 属性设置 -->属性名:属性值; <!--每一个…...

【ROS】RViz2源码分析(二):main函数及编译配置详解
【ROS】郭老二博文之:ROS目录 1、main函数 #include <memory> #include <string> #include <vector>#include <QApplication>...

Vue.js的生命周期钩子
聚沙成塔每天进步一点点 ⭐ 专栏简介 前端入门之旅:探索Web开发的奇妙世界 欢迎来到前端入门之旅!感兴趣的可以订阅本专栏哦!这个专栏是为那些对Web开发感兴趣、刚刚踏入前端领域的朋友们量身打造的。无论你是完全的新手还是有一些基础的开发…...

第3章:搜索与图论【AcWing】
文章目录 图的概念图的概念图的分类有向图和无向图 连通性连通块重边和自环稠密图和稀疏图参考资料 图的存储方式邻接表代码 邻接矩阵 DFS全排列问题题目描述思路回溯标记剪枝代码时间复杂度 [N 皇后问题](https://www.luogu.com.cn/problem/P1219)题目描述全排列思路 O ( n ! …...

C++ Qt 学习(七):Qt 线程与并发
1. Qt 创建线程的三种方法 1.1 方式一:派生于 QThread 派生于 QThread,这是 Qt 创建线程最常用的方法,重写虚函数 void QThread::run(),在 run() 写具体的内容,外部通过 start 调用,即可执行线程体 run() …...