前言

本文小新为大家带来 Redis 主从集群 相关知识,具体内容包括哨兵机制实现(包括:哨兵机制简介Redis 高可用集群搭建Redis 高可用集群的启动Sentinel 优化配置),哨兵机制原理(包括:三个定时任务Redis 节点下线判断Sentinel Leader 选举master 选择算法故障转移过程节点上线),CAP 定理(包括:CAP 概念CAP 定理BASE 理论CAP 的应用),Raft 算法(包括:Raft 算法基础角色、任期及角色转变leader 选举数据同步脑裂Leader 宕机处理Raft 算法动画演示)等进行详尽介绍~

不积跬步,无以至千里;不积小流,无以成江海。每天进步一点点,在成为强者的路上,小新与大家共同成长!

博主主页:小新要变强 的主页
Java全栈学习路线可参考:【Java全栈学习路线】最全的Java学习路线及知识清单,Java自学方向指引,内含最全Java全栈学习技术清单~
算法刷题路线可参考:算法刷题路线总结与相关资料分享,内含最详尽的算法刷题路线指南及相关资料分享~
Java微服务开源项目可参考:企业级Java微服务开源项目(开源框架,用于学习、毕设、公司项目、私活等,减少开发工作,让您只关注业务!)

↩️本文上接:超详细Redis入门教程——Redis 主从集群(上)


目录

Redis 主从集群

  • 前言
  • 目录
  • 三、哨兵机制实现
    • 1️⃣简介
    • 2️⃣Redis 高可用集群搭建
    • 3️⃣Redis 高可用集群的启动
    • 4️⃣Sentinel 优化配置
  • 四、哨兵机制原理
    • 1️⃣三个定时任务
    • 2️⃣Redis 节点下线判断
    • 3️⃣Sentinel Leader 选举
    • 4️⃣master 选择算法
    • 5️⃣故障转移过程
    • 6️⃣节点上线
  • 五、CAP 定理
    • 1️⃣概念
    • 2️⃣定理
    • 3️⃣BASE 理论
    • 4️⃣CAP 的应用
  • 六、Raft 算法
    • 1️⃣基础
    • 2️⃣角色、任期及角色转变
    • 3️⃣leader 选举
    • 4️⃣数据同步
    • 5️⃣脑裂
    • 6️⃣Leader 宕机处理
    • 7️⃣Raft 算法动画演示
  • 后记

三、哨兵机制实现

1️⃣简介

对于 Master 宕机后的冷处理方式是无法实现高可用的。Redis 从 2.6 版本开始提供了高可用的解决方案—— Sentinel 哨兵机制。在集群中再引入一个节点,该节点充当 Sentinel 哨兵,用于监视 Master 的运行状态,并在 Master 宕机后自动指定一个 Slave 作为新的 Master。整个过程无需人工参与,完全由哨兵自动完成。

不过,此时的 Sentinel 哨兵又成为了一个单点故障点:若哨兵发生宕机,整个集群将瘫痪。所以为了解决 Sentinel 的单点问题,又要为 Sentinel 创建一个集群,即 Sentinel 哨兵集群。一个哨兵的宕机,将不会影响到 Redis 集群的运行。

那么这些 Sentinel 哨兵是如何工作的呢?Sentinel 是如何知道其监视的 Master 状态的呢?每个 Sentinel 都会定时会向 Master 发送心跳,如果 Master 在有效时间内向它们都进行了响应,则说明 Master 是“活着的”。如果 Sentinel 中有 quorum 个哨兵没有收到响应,那么就认为 Master 已经宕机,然后会有一个 Sentinel 做 Failover 故障转移。即将原来的某一个 Slave晋升为 Master。

2️⃣Redis 高可用集群搭建

在“不差钱”的情况下,可以让 Sentinel 占用独立的主机,即在 Redis 主机上只启动 Redis进程,在 Sentinel 主机上只启动 Sentinel 进程。下面要搭建一个“一主二从三哨兵”的高可用伪集群,即这些角色全部安装运行在一台主机上。“一主二从”使用前面的主从集群,下面仅搭建一个 Sentinel 伪集群。

(1) 复制 sentinel.conf

将 Redis 安装目录中的 sentinel.conf 文件复制到 cluster 目录中。该配置文件中用于存放一些 sentinel 集群中的一些公共配置。

(2) 修改 sentinel.conf

修改 cluster/sentinel.conf 配置文件。

A、sentinel monitor

该配置用于指定 Sentinel 要监控的 master 是谁,并为 master 起了一个名字。该名字在后面很多配置中都会使用。同时指定 Sentinel 集群中决定该master“客观下线状态”判断的法定 sentinel 数量。的另一个用途与sentinel 的 Leader 选举有关。要求中至少要有 max(quorum, sentinelNum/2+1)个 sentinel 参与,
选举才能进行。

这里将该配置注释掉,因为要在后面的其它配置文件中设置,如果不注释就会出现配置冲突。

B、 sentinel auth-pass

如果 Redis 主从集群中的主机设置了访问密码,那么该属性就需要指定 master 的主机名与访问密码。以方便 sentinel 监控 master。

(3) 新建 sentinel26380.conf

在 Redis 安装目录下的 cluster 目录中新建 sentinel26380.conf 文件作为 Sentinel 的配置文件,并在其中键入如下内容:

sentinel monitor 属性用于指定当前监控的 master 的 IP 与 Port,同时为集群中 master 指定一个名称 mymaster,以方便其它属性使用。

最后的 2 是参数 quorum 的值,quorum 有两个用途。一个是只有当 quorum 个 sentinel都认为当前 master 宕机了才能开启故障转移。另一个用途与 sentinel 的 Leader 选举有关。要求中至少要有 max(quorum, sentinelNum/2+1)个 sentinel 参与,选举才能进行。

(4) 再复制两个 conf 文件

再使用sentinel26380.conf 复制出两个conf文件:sentinel26381.conf与sentinel26382.conf。然后修改其中的内容。

修改 sentinel26381.conf。

修改 sentinel26382.conf。

3️⃣Redis 高可用集群的启动

(1) 启动并关联 Redis 集群

首先要启动三台 Redis,然后再通过 slaveof 关联它们。

(2) 启动 Sentinel 集群

A、启动命令

在/usr/local/bin 目录下有一个命令 redis-sentinel 用于启动 Sentinel。不过,我们发现一个奇怪的现象:/usr/local/bin 目录中的 redis-sentinel 命令是 redis-server 命令的软链接,这是为什么呢?

查看 Redis 安装目录中的 src 目录中的 redis-server 与 redis-sentinel 命令,我们发现这两个命令的大小一模一样。其实,这两个命令本质上是同一个命令。

只所以可以启动不同的进程,主要是因为在启动时所加载的配置文件的不同。所以在启动 Sentinel 时,需要指定 sentinel.conf 配置文件。

B、 两种启动方式

由于 redis-server 与 redis-sentinel 命令本质上是同一个命令,所以使用这两个命令均可启动 Sentinel。

  • 方式一,使用 redis-sentinel 命令:redis-sentinel sentinel26380.conf
  • 方式二,使用 redis-server 命令:redis-server sentinel26380.conf –sentinel

C、 启动三台 Sentinel

(3) 查看 Sentinel 信息

运行中的 Sentinel 就是一个特殊 Redis,其也可以通过客户端连接,然后通过 info sentinel来查看当前连接的 Sentinel 的信息。

(4) 查看 sentinel 配置文件

打开任意 sentinel 的配置文件,发现其配置内容中新增加了很多配置。

4️⃣Sentinel 优化配置

在公共的 sentinel.conf 文件中,还可以通过修改一些其它属性的值来达到对 Sentinel 的配置优化。

(1) sentinel down-after-milliseconds

每个 Sentinel 会通过定期发送 ping 命令来判断 master、slave 及其它 Sentinel 是否存活。如果 Sentinel 在该属性指定的时间内没有收到它们的响应,那么该 Sentinel 就会主观认为该主机宕机。默认为 30 秒。

(2) sentinel parallel-syncs

该属性用于指定,在故障转移期间,即老的 master 出现问题,新的 master 刚晋升后,允许多少个 slave 同时从新 master 进行数据同步。默认值为 1 表示所有 slave 逐个从新 master进行数据同步。

(3) sentinel failover-timeout

指定故障转移的超时时间,默认时间为 3 分钟。该超时时间的用途很多:

  • 由于第一次故障转移失败,在同一个 master 上进行第二次故障转移尝试的时间为该failover-timeout 的两倍
  • 新 master晋升完毕,slave 从老master 强制转到新 master 进行数据同步的时间阈值。
  • 取消正在进行的故障转换所需的时间阈值。
  • 新 master 晋升完毕,所有 replicas 的配置文件更新为新 master 的时间阈值。

(4) sentinel deny-scripts-reconfig

指定是否可以通过命令 sentinel set 动态修改 notification-script 与 client-reconfig-script 两个脚本。默认是不能的。这两个脚本如果允许动态修改,可能会引发安全问题。

(5) 动态修改配置

通过 redis-cli 连接上 Sentinel 后,通过 sentinel set 命令可动态修改配置信息。例如,下面的命令动态修改了 sentinel monitor 中的 quorum 的值。

下表是 sentinel set 命令支持的参数:

四、哨兵机制原理

1️⃣三个定时任务

Sentinel 维护着三个定时任务以监测 Redis 节点及其它 Sentinel 节点的状态。

(1) info 任务

每个 Sentinel 节点每 10 秒就会向 Redis 集群中的每个节点发送 info 命令,以获得最新的Redis 拓扑结构。

(2) 心跳任务

每个Sentinel节点每1秒就会向所有Redis节点及其它Sentinel节点发送一条ping命令,以检测这些节点的存活状态。该任务是判断节点在线状态的重要依据。

(3) 发布/订阅任务

每个 Sentinel 节点在启动时都会向所有 Redis 节点订阅 _ sentinel _:hello 主题的信息,当 Redis 节点中该主题的信息发生了变化,就会立即通知到所有订阅者。

启动后,每个 Sentinel 节点每 2 秒就会向每个 Redis 节点发布一条_ sentinel_:hello 主题的信息,该信息是当前 Sentinel 对每个 Redis 节点在线状态的判断结果及当前 Sentinel 节点信息。

当 Sentinel 节点接收到_ sentinel_:hello 主题信息后,就会读取并解析这些信息,然后主要完成以下三项工作:

  • 如果发现有新的 Sentinel 节点加入,则记录下新加入 Sentinel 节点信息,并与其建立连接。
  • 如果发现有 Sentinel Leader 选举的选票信息,则执行 Leader 选举过程。
  • 汇总其它 Sentinel 节点对当前 Redis 节点在线状态的判断结果,作为 Redis 节点客观下线的判断依据。

2️⃣Redis 节点下线判断

对于每个 Redis 节点在线状态的监控是由 Sentinel 完成的。

(1) 主观下线

每个 Sentinel 节点每秒就会向每个 Redis 节点发送 ping 心跳检测,如果 Sentinel 在down-after-milliseconds 时间内没有收到某 Redis 节点的回复,则 Sentinel 节点就会对该 Redis节点做出“下线状态”的判断。这个判断仅仅是当前 Sentinel 节点的“一家之言”,所以称为主观下线。

(2) 客观下线

当 Sentinel 主观下线的节点是 master 时,该 Sentinel 节点会向每个其它 Sentinel 节点发送 sentinel is-master-down-by-addr 命令,以询问其对 master 在线状态的判断结果。这些Sentinel 节点在收到命令后会向这个发问 Sentinel 节点响应 0(在线)或 1(下线)。当 Sentinel收到超过 quorum 个下线判断后,就会对 master 做出客观下线判断。

3️⃣Sentinel Leader 选举

当 Sentinel 节点对 master 做出客观下线判断后会由 Sentinel Leader 来完成后续的故障转移,即 Sentinel 集群中的节点也并非是对等节点,是存在 Leader 与 Follower 的。

Sentinel 集群的 Leader 选举是通过 Raft 算法实现的。Raft 算法比较复杂,后面会详细学习。这里仅简单介绍一下大致思路。

每个选举参与者都具有当选 Leader 的资格,当其完成了“客观下线”判断后,就会立即“毛遂自荐”推选自己做 Leader,然后将自己的提案发送给所有参与者。其它参与者在收到提案后,只要自己手中的选票没有投出去,其就会立即通过该提案并将同意结果反馈给提案者,后续再过来的提案会由于该参与者没有了选票而被拒绝。当提案者收到了同意反馈数量大于等于 max(quorum,sentinelNum/2+1)时,该提案者当选 Leader。

说明:

  • 在网络没有问题的前提下,基本就是谁先做出了“客观下线”判断,谁就会首先发起Sentinel Leader的选举,谁就会得到大多数参与者的支持,谁就会当选 Leader。
  • Sentinel Leader 选举会在次故障转移发生之前进行。
  • 故障转移结束后 Sentinel 不再维护这种 Leader-Follower 关系,即 Leader 不再存在。

4️⃣master 选择算法

在进行故障转移时,Sentinel Leader 需要从所有 Redis 的 Slave 节点中选择出新的 Master。

其选择算法为:

  • 过滤掉所有主观下线的,或心跳没有响应 Sentinel 的,或 replica-priority 值为 0 的 Redis节点
  • 在剩余 Redis 节点中选择出 replica-priority 最小的的节点列表。如果只有一个节点,则直接返回,否则,继续
  • 从优先级相同的节点列表中选择复制偏移量最大的节点。如果只有一个节点,则直接返回,否则,继续
  • 从复制偏移值量相同的节点列表中选择动态 ID 最小的节点返回

5️⃣故障转移过程

Sentinel Leader 负责整个故障转移过程,经历了如上步骤:

  • Sentinel Leader 根据 master 选择算法选择出一个 slave 节点作为新的 master
  • Sentinel Leader 向新 master 节点发送 slaveof no one 指令,使其晋升为 master
  • Sentinel Leader 向新 master 发送 info replication 指令,获取到 master 的动态 ID
  • Sentinel Leader 向其余 Redis 节点发送消息,以告知它们新 master 的动态 ID
  • Sentinel Leader 向其余 Redis 节点发送 slaveof 指令,使它们成为新master 的 slave
  • Sentinel Leader 从所有 slave 节点中每次选择出 parallel-syncs 个 slave 从新 master同步数据,直至所有 slave 全部同步完毕
  • 故障转移完毕

6️⃣节点上线

不同的节点类型,其上线的方式也是不同的。

(1) 原 Redis 节点上线

无论是原下线的 master 节点还是原下线的 slave 节点,只要是原 Redis 集群中的节点上线,只需启动 Redis 即可。因为每个 Sentinel 中都保存有原来其监控的所有 Redis 节点列表,Sentinel 会定时查看这些 Redis 节点是否恢复。如果查看到其已经恢复,则会命其从当前master 进行数据同步。

不过,如果是原 master 上线,在新 master 晋升后 Sentinel Leader 会立即先将原 master节点更新为 slave,然后才会定时查看其是否恢复。

(2) 新 Redis 节点上线

如果需要在 Redis 集群中添加一个新的节点,其未曾出现在 Redis 集群中,则上线操作只能手工完成。即添加者在添加之前必须知道当前 master 是谁,然后在新节点启动后运行slaveof 命令加入集群。

(3) Sentinel 节点上线

如果要添加的是 Sentinel 节点,无论其是否曾经出现在 Sentinel 集群中,都需要手工完成。即添加者在添加之前必须知道当前 master 是谁,然后在配置文件中修改 sentinel monitor属性,指定要监控的 master。然后启动 Sentinel 即可。

五、CAP 定理

1️⃣概念

CAP 定理指的是在一个分布式系统中,一致性 Consistency、可用性 Availability、分区容错性 Partition tolerance,三者不可兼得。

  • 一致性(C):分布式系统中多个主机之间是否能够保持数据一致的特性。即,当系统数据发生更新操作后,各个主机中的数据仍然处于一致的状态。
  • 可用性(A):系统提供的服务必须一直处于可用的状态,即对于用户的每一个请求,系统总是可以在有限的时间内对用户做出响应。
  • 分区容错性(P):分布式系统在遇到任何网络分区故障时,仍能够保证对外提供满足一致性和可用性的服务。

2️⃣定理

CAP 定理的内容是:对于分布式系统,网络环境相对是不可控的,出现网络分区是不可避免的,因此系统必须具备分区容错性。但系统不能同时保证一致性与可用性。即要么 CP,要么 AP。

3️⃣BASE 理论

BASE 是 Basically Available(基本可用)、Soft state(软状态)和 Eventually consistent(最终一致性)三个短语的简写,BASE 是对 CAP 中一致性和可用性权衡的结果,其来源于对大规模互联网系统分布式实践的结论,是基于 CAP 定理逐步演化而来的。

BASE 理论的核心思想是:即使无法做到强一致性,但每个系统都可以根据自身的业务特点,采用适当的方式来使系统达到最终一致性。

(1) 基本可用

基本可用是指分布式系统在出现不可预知故障的时候,允许损失部分可用性。

(2) 软状态

软状态,是指允许系统数据存在的中间状态,并认为该中间状态的存在不会影响系统的整体可用性,即允许系统主机间进行数据同步的过程存在一定延时。软状态,其实就是一种灰度状态,过渡状态。

(3) 最终一致性

最终一致性强调的是系统中所有的数据副本,在经过一段时间的同步后,最终能够达到一个一致的状态。因此,最终一致性的本质是需要系统保证最终数据能够达到一致,而不需要保证系统数据的实时一致性。

4️⃣CAP 的应用

下面将生产中常见到的一些中间件与服务器集群的 CAP 特性进行分析。

(1) Zookeeper 与 CAP

Zookeeper 遵循的是 CP 模式,即保证了一致性,但牺牲了可用性。

当 Leader 节点中的数据发生了变化后,在 Follower 还没有同步完成之前,整个 Zookeeper集群是不对外提供服务的。如果此时有客户端来访问数据,则客户端会因访问超时而发生重试。不过,由于 Leader 的选举非常快,所以这种重试对于用户来说几乎是感知不到的。所以说,Zookeeper 保证了一致性,但牺牲了可用性。

(2) Consul 与 CAP

Consul 遵循的是 CP 模式,即保证了一致性,但牺牲了可用性。

(3) Redis 与 CAP

Redis 遵循的是 AP 模式,即保证了可用性,但牺牲了一致性。

(4) Eureka 与 CAP

Eureka 遵循的是 AP 模式,即保证了可用性,但牺牲了一致性。

(5) Nacos 与 CAP

Nacos 在做注册中心时,默认是 AP 的。但其也支持 CP 模式,但需要用户提交请求进行转换。

六、Raft 算法

1️⃣基础

Raft 算法是一种通过对日志复制管理来达到集群节点一致性的算法。这个日志复制管理发生在集群节点中的 Leader 与 Followers 之间。Raft 通过选举出的 Leader 节点负责管理日志复制过程,以实现各个节点间数据的一致性。

2️⃣角色、任期及角色转变

在 Raft 中,节点有三种角色:

  • Leader:唯一负责处理客户端写请求的节点;也可以处理客户端读请求;同时负责日志复制工作
  • Candidate:Leader 选举的候选人,其可能会成为 Leader。是一个选举中的过程角色
  • Follower:可以处理客户端读请求;负责同步来自于 Leader 的日志;当接收到其它
  • Cadidate 的投票请求后可以进行投票;当发现 Leader 挂了,其会转变为 Candidate 发起Leader 选举

3️⃣leader 选举

通过 Raft 算法首先要实现集群中 Leader 的选举。

(1) 我要选举

若 follower 在心跳超时范围内没有接收到来自于 leader 的心跳,则认为 leader 挂了。此时其首先会使其本地 term 增一。然后 follower 会完成以下步骤:

  • 此时若接收到了其它 candidate 的投票请求,则会将选票投给这个 candidate
  • 由 follower 转变为 candidate
  • 若之前尚未投票,则向自己投一票
  • 向其它节点发出投票请求,然后等待响应

(2) 我要投票

follower 在接收到投票请求后,其会根据以下情况来判断是否投票:

  • 发来投票请求的 candidate 的 term 不能小于我的 term
  • 在我当前 term 内,我的选票还没有投出去
  • 若接收到多个 candidate 的请求,我将采取 first-come-first-served 方式投票

(3) 等待响应

当一个 Candidate 发出投票请求后会等待其它节点的响应结果。这个响应结果可能有三种情况:

  • 收到过半选票,成为新的 leader。然后会将消息广播给所有其它节点,以告诉大家我是新的 Leader 了
  • 接收到别的 candidate 发来的新 leader 通知,比较了新 leader 的 term 并不比自己的 term小,则自己转变为follower
  • 经过一段时间后,没有收到过半选票,也没有收到新 leader 通知,则重新发出选举

(4) 选举时机

在很多时候,当 Leader 真的挂了,Follower 几乎同时会感知到,所以它们几乎同时会变为 candidate 发起新的选举。此时就可能会出现较多 candidate 票数相同的情况,即无法选举出 Leader。

为了防止这种情况的发生,Raft 算法其采用了 randomized election timeouts 策略来解决这个问题。其会为这些 Follower 随机分配一个选举发起时间 election timeout,这个 timeout在 150-300ms 范围内。只有到达了 election timeout 时间的 Follower 才能转变为 candidate,否则等待。那么 election timeout 较小的 Follower 则会转变为 candidate 然后先发起选举,一般情况下其会优先获取到过半选票成为新的 leader。

4️⃣数据同步

在 Leader 选举出来的情况下,通过日志复制管理实现集群中各节点数据的同步。

(1) 状态机

Raft 算法一致性的实现,是基于日志复制状态机的。状态机的最大特征是,不同 Server中的状态机若当前状态相同,然后接受了相同的输入,则一定会得到相同的输出。


(2) 处理流程

当 leader 接收到 client 的写操作请求后,大体会经历以下流程:

  • leader 在接收到 client 的写操作请求后,leader 会将数据与 term 封装为一个 box,并随着下一次心跳发送给所有followers,以征求大家对该 box 的意见。同时在本地将数据封装为日志
  • follower 在接收到来自 leader 的 box 后首先会比较该 box 的 term 与本地记录的曾接受过的 box 的最大term,只要不比自己的小就接受该 box,并向 leader 回复同意。同时会将该 box 中的数据封装为日志。
  • 当 leader 接收到过半同意响应后,会将日志 commit 到自己的状态机,状态机会输出一个结果,同时日志状态变为了committed
  • 同时 leader 还会通知所有 follower 将日志 commit 到它们本地的状态机,日志状态变为了 committed
  • 在 commit 通知发出的同时,leader 也会向 client 发出成功处理的响应

(3) AP 支持

Log 由 term index、log index 及 command 构成。为了保证可用性,各个节点中的日志可以不完全相同,但 leader 会不断给 follower 发送 box,以使各个节点的 log 最终达到相同。即 raft 算法不是强一致性的,而是最终一致的。

5️⃣脑裂

Raft 集群存在脑裂问题。在多机房部署中,由于网络连接问题,很容易形成多个分区。而多分区的形成,很容易产生脑裂,从而导致数据不一致。

由于三机房部署的容灾能力最强,所以生产环境下,三机房部署是最为常见的。下面以三机房部署为例进行分析,根据机房断网情况,可以分为五种情况:

(1) 情况一–不确定

这种情况下,B 机房中的主机是感知不到 Leader 的存在的,所以 B 机房中的主机会发起新一轮的 Leader 选举。由于 B 机房与 C 机房是相连的,虽然 C 机房中的 Follower 能够感知到 A 机房中的 Leader,但由于其接收到了更大 term 的投票请求,所以 C 机房的 Follower也就放弃了 A 机房中的 Leader,参与了新 Leader 的选举。

若新 Leader 出现在 B 机房,A 机房是感知不到新 Leader 的诞生的,其不会自动下课,所以会形成脑裂。但由于 A 机房 Leader 处理的写操作请求无法获取到过半响应,所以无法完成写操作。但 B 机房 Leader 的写操作处理是可以获取到过半响应的,所以可以完成写操作。故,A 机房与 B、C 机房中出现脑裂,且形成了数据的不一致。

若新 Leader 出现在 C 机房,A 机房中的 Leader 则会自动下课,所以不会形成脑裂。

(2) 情况二–形成脑裂

这种情况与情况一基本是一样的。不同的是,一定会形成脑裂,无论新 Leader 在 B 还是 C 机房。

(3) 情况三–无脑裂

A、C 可以正常对外提供服务,但 B 无法选举出新的 Leader。由于 B 中的主机全部变为了选举状态,所以无法提供任何服务,没有形成脑裂。

(4) 情况四–无脑裂

A、B、C 均可以对外提供服务,不受影响。

(5) 情况五–无脑裂

A 机房无法处理写操作请求,但可以对外提供读服务。

B、C 机房由于失去了 Leader,均会发起选举,但由于均无法获取过半支持,所以均无法选举出新的 Leader。

6️⃣Leader 宕机处理

(1) 请求到达前 Leader 挂了

client 发送写操作请求到达 Leader 之前 Leader 就挂了,因为请求还没有到达集群,所以这个请求对于集群来说就没有存在过,对集群数据的一致性没有任何影响。Leader 挂了之后,会选举产生新的 Leader。

由于 Stale Leader 并未向 client 发送成功处理响应,所以 client 会重新发送该写操作请求。

(2) 未开始同步数据前 Leader 挂了

client 发送写操作请求给 Leader,请求到达 Leader 后,Leader 还没有开始向 Followers发出数据 Leader 就挂了。这时集群会选举产生新的 Leader。Stale Leader 重启后会作为Follower 重新加入集群,并同步新 Leader 中的数据以保证数据一致性。之前接收到 client 的数据被丢弃。

由于 Stale Leader 并未向 client 发送成功处理响应,所以 client 会重新发送该写操作请求。

(3) 同步完部分后 Leader 挂了

client 发送写操作请求给 Leader,Leader 接收完数据后向所有 Follower 发送数据。在部分 Follower 接收到数据后 Leader 挂了。由于 Leader 挂了,就会发起新的 Leader 选举。

  • 若 Leader 产生于已完成数据接收的 Follower,其会继续将前面接收到的写操作请求转换为日志,并写入到本地状态机,并向所有Flollower 发出询问。在获取过半同意响应后会向所有 Followers 发送 commit 指令,同时向 client 进行响应。
  • 若 Leader 产生于尚未完成数据接收的 Follower,那么原来已完成接收的Follower 则会放弃曾接收到的数据。由于client 没有接收到响应,所以 client 会重新发送该写操作请求。

(4) commit 通知发出后 Leader 挂了

client 发送写操作请求给 Leader,Leader 也成功向所有 Followers 发出的 commit 指令,并向 client 发出响应后,Leader 挂了。

由于 Stale Leader 已经向 client 发送成功接收响应,且 commit 通知已经发出,说明这个写操作请求已经被 server 成功处理。

7️⃣Raft 算法动画演示

在网络上有一个关于 Raft 算法的动画,其非常清晰全面地演示了 Raft 算法的工作原理。

该动画的地址为:http://thesecretlivesofdata.com/raft/


后记

Java全栈学习路线可参考:【Java全栈学习路线】最全的Java学习路线及知识清单,Java自学方向指引,内含最全Java全栈学习技术清单~
算法刷题路线可参考:算法刷题路线总结与相关资料分享,内含最详尽的算法刷题路线指南及相关资料分享~