Redis 7.x 系列【29】集群原理之自动故障转移

news/2024/9/20 7:27:32/ 标签: redis, 缓存, 高性能

有道无术,术尚可求,有术无道,止于术。

本系列Redis 版本 7.2.5

源码地址:https://gitee.com/pearl-organization/study-redis-demo

文章目录

    • 1. 概述
    • 2. 案例演示
    • 3. 工作原理
      • 3.1 故障检测
      • 3.2 排名
      • 3.3 延迟等待
      • 3.4 投票
      • 3.5 上位

1. 概述

官方文档

Redis 集群的某些节点出现故障时,可以自动进行故障转移,地将从节点提升为主节点,保证服务的连续性和数据的可用性。

也可以手动进行故障转移,会在集群命令篇进行讲解

2. 案例演示

当前环境中,有一个三主三从的 Redis 集群(一台机器部署),主从节点的对应关系如下:

主节点从节点
192.168.56.101:6379192.168.56.101:6382
192.168.56.101:6380192.168.56.101:6383
192.168.56.101:6381192.168.56.101:6390

192.168.56.101:6379 节点上,使用 cluster nodes 命令可以看到,当前是一个主节点:

主节点(192.168.56.101:6379)>cluster nodes
724c7b874dc0c37a462cd5ab59325203344f8008 192.168.56.101:6379@16379 myself,master - 0 1720733735000 1 connected 0-5460

直接使用 kill 命令关闭 192.168.56.101:6379 节点:

[root@localhost bin]# ps -ef | grep  redis
root      2586     1  1 7月11 ?       00:07:00 ./redis-server *:6379 [cluster]
root      7921  7683  0 06:01 pts/2    00:00:00 grep --color=auto redis
[root@localhost bin]# kill -9 2586

立即查看节点信息,可以看到 192.168.56.101:6379 节点被标记为失败状态,之前对应的从节点 192.168.56.101:6382 自动升级为主节点:
在这里插入图片描述
192.168.56.101:6379 节点再次上线后,可以看到变成了从节点:
在这里插入图片描述

3. 工作原理

集群中所有节点,都会包含一下两个 Epoch 信息,并在心跳数据包中进行传播,类似于 Raft 中的 term ,用于解决节点信息、配置的冲突问题。

这里简要概括下,具体在官方文档有详细说明:

  • Current Epoch:当多个节点提供相互冲突的信息时,用于够判断出哪个状态是最新的,值越高越新
  • Config Epoch :翻译为配置时期、配置版本,它主要用于解决节点间配置冲突和确保配置的一致性,值越高越新

3.1 故障检测

Redis Cluster 会通过心跳检测迅速感知到节点故障,并且在节点故障时自动进行恢复,以确保数据在集群中的可用性。当心跳检测到节点不能被大多数节点访问时,会通过提升从节点为主节点来自动修复,当从节点无法升级时,集群将进入错误状态,停止接收客户端的查询操作。

每个集群节点内部都维护一个与其他已知节点相关的标记映射表,用于进行故障检测和状态管理。
在这里插入图片描述

在故障检测中,使用了两个标记:

  • PFAILPossibly FAILed):可能的故障,是一种未确认的故障类型,类似于哨兵中的主观下线
  • FAIL:真正的故障,由集群中大多数主节点确认,类似于哨兵中的客观下线

当一个节点在超过 NODE_TIMEOUT (默认为 15 秒)时间后仍然无法访问时,该节点会将另一个节点标记为 PFAIL。 检测到其他节点为 PFAIL 状态的信息首先会保存在本地,然后通过 Gossip 发送到其他所有节点,最终,每个节点,都会收到某个节点的 PFAIL 标记。

PFAIL 标记并不足以触发从节点的提升,需要升级为 FAIL 状态。例如, B 宕机后,整个状态升级过程如下:

  • AB 节点发送 Ping 后, 在 15 秒后还没有返回响应,则将 B 标记为 PFAIL ,并存储在本地信息文件中。
  • 其他节点也检测到 B 的状态,并在本地标记为 PFAIL
  • A 节点通过 Gossip 获取到其他节点关于 B 节点的 PFAIL 状态
  • NODE_TIMEOUT * FAIL_REPORT_VALIDITY_MULT (超时时间 * 有效性因子)时间内,比如有效性因子设置为 2 ,那么在 30 秒内,大多数主节点都标记了 B 节点为 PFAIL 状态,A 节点会将 B 升级为 FAIL 状态
  • A 向所有节点发送 B 已经 FAIL 的信息,其他节点收到消息后,也将 B 更新为 FAIL

FAIL 状态可以在以下情况下被清除:

  • 节点已经可达且是从节点,因为从节点不会被故障转移。
  • 节点已经可达且是主节点,但是没有分配哈希槽,因为没有槽位的主节点实际上并不参与集群,并正在等待被配置以加入集群。

3.2 排名

当主节点发生故障时,从节点会交换消息建立排名,拥有最新复制偏移量的复制节点排名为 0 ,第二新的排名为 1 ,依此类推,最新的从节点会优先尝试选举。

排名顺序并不是严格执行的(尽力而为),如果排名较高的从节点未能当选,其他从节点将很快尝试选举。

3.3 延迟等待

一旦主节点进入 FAIL 状态,从节点会在尝试选举之前等待一段短暂的时间。确保 FAIL 状态在整个集群中传播,否则某个主节点不知道其他节点的 FAIL 状态,会拒绝投票。

延迟等待时间的计算公式如下:

DELAY = 500 毫秒 + 0到500毫秒之间的随机延迟 + REPLICA_RANK * 1000毫秒

公式各部分说明如下:

  • 随机延迟:用于使从节点的选举时间不同步,以免它们同时开始选举。
  • REPLICA_RANK:从节点在处理来自主节点的复制数据量方面的排名

3.4 投票

从节点的选举和晋升由从节点处理,并通过主节点的投票来支持从节点的升级。

从节点在满足以下条件时才会启动选举:

  • 对应的主节点处于 FAIL 状态
  • 主节点分配了可服务的哈希槽
  • 与主节点的复制连接断开的时间不超过一定的时长,以确保升级后从节点数据是相对较新的

从节点通过向集群中的每个主节点广播一个 FAILOVER_AUTH_REQUEST 数据包来请求投票,超时时间为 NODE_TIMEOUT 时间的两倍(最少 2 秒)。

主节点投票后,会通过 FAILOVER_AUTH_ACK 进行回复,并在接下来 NODE_TIMEOUT * 2 的时间内,不能为同一主节点的其他从节点投票。

3.5 上位

当某个从节点收到了大多数主节点的 ACK 回复,说明赢得了选举。如果在两倍 NODE_TIMEOUT 的时间内未达到多数,选举将被中止,然后将在 NODE_TIMEOUT * 4 后再次尝试。

赢得选举后,从节点将获得一个新的唯一递增的 configEpoch ,该值高于任何现有主节点的 configEpoch ,并通过 Ping 广播到集群中的所有节点,告知自己是主节点,并携带自己分配的哈希槽信息。

对于广播不可达的节点,还会通过心跳机制,传播到其他节点,收到消息后,发现 configEpoch 最高,所以也会及时更新本地信息。


http://www.ppmy.cn/news/1501442.html

相关文章

LeetCode:相同的树(C语言)

1、问题概述:给2个二叉树的根节点p和q,如果2个树在结构和数值上都相同才为true,否则为false 2、示例 示例 1: 输入:p [1,2,3], q [1,2,3] 输出:true 示例 2: 输入:p [1,2], q […

软件开发者消除edge浏览器下载时“此应用不安全”的拦截方法

当Microsoft Edge浏览器显示“此应用不安全”或者“已阻止此不安全的下载”这类警告时,通常是因为Windows Defender SmartScreen或者其他安全功能认为下载的文件可能存在安全风险。对于软件开发者来说,大概率是由于软件没有进行数字签名,导致…

Java 中对象List 转map实践

class MyObject {Long id;String name;// Constructorpublic MyObject(Long id, String name) {this.id id;this.name name;}// Getterspublic Long getId() {return id;}public String getName() {return name;} }第一种 List 转 Map<Long, String> List<MyObject…

Codeforces Round 962 (Div. 3)

A题 Legs 题目&#xff1a; 农夫约翰的农场又迎来了美好的一天。 农夫约翰到达他的农场后&#xff0c;他数了数 n条 腿。众所周知&#xff0c;只有鸡和牛生活在农场&#xff0c;鸡有 2 条腿&#xff0c;而牛有 4 条腿 。 假设农场主约翰计算了所有动物的腿&#xff0c;他的…

2024安全大模型技术与市场研究报告

大模型驱动的AIGC引发技术革命&#xff0c;国资委强调国企需加大AI投入。大模型解决网络安全行业攻防不对等问题&#xff0c;国内外企业纷纷推出基于大模型的网络安全产品&#xff0c;AI将改变网络安全产品格局。 自 2022 年底开始&#xff0c;以 LLM(大语言模型&#xff0c;简…

magento2 安装win环境和linux环境

win10 安装 安装前提&#xff0c;php,mysql,apach 或nginx 提前安装好 并且要php配置文件里&#xff0c;php.ini 把错误打开 display_errorsOn开始安装 检查环境 填写数据库信息 和ssl信息&#xff0c;如果ssl信息没有&#xff0c;则可以忽略 填写域名和后台地址&#xff0…

tp5/6 查询MySQL某字段逗号分隔的数字与给定数组里的多个值匹配

记录&#xff1a;如果一个字段存储的是逗号分隔的数字&#xff0c;并且你希望查询这个字段中的值是否与给定数组中的任意元素相匹配&#xff0c;你可以考虑使用 SQL 的 FIND_IN_SET 函数配合循环构造动态查询条件。 示例 // 假设你的模型是 User&#xff0c;字段名为 id_list&…

创维汽车滁州永通体验中心开业仪式暨超充车型区域上市会圆满成功

2024年7月20日&#xff0c;创维汽车滁州永通体验中心盛大开业&#xff0c;当日&#xff0c;创维汽车市场部经理周世鹏、安徽大区总监王大明等领导参加本次开业盛典&#xff0c;共同见证创维汽车滁州永通体验中心成功落地。 2021年&#xff0c;新能源乘用车高速发展&#xff0c;…

两数相加(LeetCode)

题目 给你两个 非空 的链表&#xff0c;表示两个非负的整数。它们每位数字都是按照 逆序 的方式存储的&#xff0c;并且每个节点只能存储 一位 数字。 请你将两个数相加&#xff0c;并以相同形式返回一个表示和的链表。 你可以假设除了数字 0 之外&#xff0c;这两个数都不会以…

大数据——Hive原理

摘要 Apache Hive 是一个基于 Hadoop 分布式文件系统 (HDFS) 的数据仓库软件项目&#xff0c;专为存储和处理大规模数据集而设计。它提供类似 SQL 的查询语言 HiveQL&#xff0c;使用户能够轻松编写复杂的查询和分析任务&#xff0c;而无需深入了解 Hadoop 的底层实现。 Hive…

基于MindSpore Quantum的Grover搜索算法和龙算法

前言 Grover搜索算法&#xff0c;这是一种利用量子状态叠加性进行并行计算并实现加速的算法。Grover搜索算法解决了无序数据库搜索问题&#xff0c;其时间复杂度远低于经典算法&#xff0c;展示了量子计算的强大性能。文章还将通过两个小例子展示如何利用MindSpore Quantum实现…

C# Web控件与数据感应之 填充 HtmlTable

C# Web控件与数据感应之 填充 HtmlTable 在C#中&#xff0c;特别是在ASP.NET Web Forms应用中&#xff0c;你可能会遇到需要将数据动态填充到HTML表格&#xff08;HtmlTable&#xff09;中的场景。这通常涉及到遍历数据源&#xff08;如数据库查询结果、集合等&#xff09;&am…

C#中的new以及类

new关键字的用法 实例化对象&#xff1a;使用 new 关键字可以创建一个类的实例。例如&#xff1a; ​ MyClass obj new MyClass(); 指定构造函数&#xff1a;如果类有多个构造函数&#xff0c;可以使用 new 关键字指定使用哪一个构造函数来创建对象。例如&#xff1a; ​ MyC…

基于 HTML+ECharts 实现智慧运维数据可视化大屏(含源码)

智慧运维数据可视化大屏&#xff1a;基于 HTML 和 ECharts 的实现 在现代企业中&#xff0c;运维管理是确保系统稳定运行的关键环节。随着数据量的激增&#xff0c;如何高效地监控和分析运维数据成为了一个重要课题。本文将介绍如何利用 HTML 和 ECharts 实现一个智慧运维数据可…

IPython的Bash之舞:%%bash命令全解析

IPython的Bash之舞&#xff1a;%%bash命令全解析 IPython的%%bash魔术命令为Jupyter Notebook用户提供了一种在单元格中直接执行Bash脚本的能力。这个特性特别适用于需要在Notebook中运行系统命令或Bash特定功能的场景。本文将详细介绍如何在IPython中使用%%bash命令&#xff…

Linux中的fopen,fclose,fread,fwrite,fseek相关函数的知识点

这几个函数都是标准的c库函数&#xff0c;在man 2中查找不到&#xff0c;所以我们可以利用man 手册直接查找 对应的open,close,write,fread都是Linux系统内核调用 可移植性&#xff1a;fopen 强过于 open ... fopen 在用户态是缓存的 open 在用户态是没有缓存的 fopen函数 f…

Axure Web端元件库:从Quick UI到500+组件的飞跃

在快速变化的数字世界中&#xff0c;产品设计不仅仅是功能的堆砌&#xff0c;更是用户体验的精心雕琢。原型设计作为产品开发过程中的关键环节&#xff0c;其重要性不言而喻。Axure&#xff0c;作为业界领先的原型设计工具&#xff0c;凭借其强大的交互设计和丰富的功能&#x…

C++:opencv矩阵的转置--Mat.t()

在C中&#xff0c;OpenCV库是一个广泛使用的计算机视觉库&#xff0c;它提供了大量的函数和类来处理图像和视频数据。在OpenCV中&#xff0c;Mat 类是一个核心类&#xff0c;代表了一个多维的数值数组&#xff0c;可以存储图像、矩阵等。对于矩阵操作&#xff0c;Mat 类提供了许…

【java】常用加密

文章目录 1. Hash加密(摘要加密) 1. Hash加密(摘要加密) 引文&#xff1a; 如果开发者需要保存密码&#xff08;比如网站用户的密码&#xff09;&#xff0c;要考虑如何保护这些密码数据&#xff0c;网站用户密码的泄露是一件非常严重的事情&#xff0c;容易引起用户恐慌&…

ABAP 无意义的FORM 规范

发现一个极为奇怪的现象&#xff0c;大多数ABAP程序员会在FORM名称前加前缀frm_。 请问这是规范吗&#xff0c;整齐好看吗&#xff0c;又好看在哪里呢。这是哪个师傅教的&#xff0c;意义是什么&#xff1f;而且大多数人就来个frm_get_data与frm_del_data&#xff0c;然后这两…