Raft算法

154 阅读4分钟

1、概述

Raft:是一种用于分布式一致性共识算法,用于确保在分布式系统中多个节点达成一致状态。

Raft算法中包含的角色:

  1. Leader:为唯一负责处理客户端写请求的节点,也可以处理客户端读请求。同时负责向其他节点发送日志条目以进行复制,并在大多数节点同意后将日志条目提交。
  2. Follower:可以处理客户端读请求,负责同步来自 Leader 的日志。当发现 Leader 挂了,其会变成 Candidate 并发起 Leader 选举,当收到 Candidate 的投票请求后可以进行投票。
  3. Candidate:Leader 选举的候选人,是选举过程中的过程角色。

2、Leader选举

2.1 选举

若 Follower 在心跳超时范围内没有接收到来自 Leader 的心跳,则认为 Leader 挂了。此时会使其本地 term+1。然后进行以下步骤:

  1. 若接收到了其他 Candidate 的投票请求,则会将选票投给该 Candidate。
  2. 由 Follower 转变为 Candidate。
  3. 若之前尚未投票,则投自己一票。
  4. 向其他节点发出投票请求,等待响应。

2.2 投票

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

  1. 选票还没有投出去。
  2. 发来投票请求的 Candidate 的 term 不能小于我的 term。
  3. 若收到多个 Candidate 的请求,将采取 first-come-first-served 方式投票。

2.3 等待响应

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

  1. 收到过半选票:成为 Leader。然后会将消息广播给其他节点。
  2. 收到别的 Candidate 的 Leader 通知:若 Leader 的 term 大于自己 term:由 Candidate 转为 Follower。若 Leader 的 term 小于自己 term:意味着该候选者已经过时了,因为其他节点已经选举出了一个新的 Leader。
  3. 经过一段时间后,没有收到过半选票,也没有收到 Leader 通知,则重新发出选票。、

2.4 选举时机

在很多情况,Leader 挂了后,Follower 几乎同时感知到,并会几乎同时编程 Candidate 发起新的选举。此时就很可能出现多个 Candidate 票数相同的情况,即无法选举出 Leader。

为了防止这种情况,Raft 算法采用了 randomized election timeouts 策略来解决这个问题。即为 Follower 随机分配一个 election timeout(150ms~300ms),只有达到 election timeout 后 follower 才有资格称为 Candidate。

3、数据同步

数据同步的结构:

image.png

数据同步基本流程:

image.png

4、脑裂

脑裂:在分布式系统中出现的一种问题,其中网络分区导致系统中的节点被划分成了多个孤立的子集,每个子集可能都认为自己是整个系统的唯一部分。这种情况下,每个子集可能会选择自己的Leader,并且在不同的子集中可能存在不同的数据状态。

Raft算法中出现脑裂的情况:

  1. 网络分区:网络中断或故障可能导致节点之间无法进行通信,从而导致分区的出现。
  2. 选举冲突:在网络分区发生后,每个子集中的节点都发起了新的 Leader 选举,可能会导致多个 Leader 被选举出来,从而进一步加剧脑裂问题。

三机房的容灾能力最强,所以生产环境下,三机房部署是最常见的。下面以三机房部署为例分析:(三机房中任意两个机房的机器数量要大于一半)

  1. 情况1:

image.png

  1. 情况2:

image.png

  1. 情况3:

image.png

  1. 情况4:

image.png

  1. 情况5:

image.png

5、Leader宕机的情况

  1. 请求达到 Leader 之前宕机:因为请求还没到达集群,所以该请求对集群来说相当于没有存在过,对集群一致性没有任何影响。Client 重新发送该写操作即可。
  2. Leader 未开始发送数据前宕机:原 Leader 重启后作为 Follower 加入集群,并同步新 Leader 中的数据。之前收到数据被丢弃。Client 重新发送该写操作。
  3. Leader 发送部分数据后宕机:若 Follower 产生于已接收数据的 Follower:继续将前面收到的写操作转换为日志,并写入本地状态机,向所有 Follower 发出问询。在获取过半同意后会向所有 Follower 发送 commit 命令,同时响应 Client。若 Follower 产生与未接收数据的 Follower:已接收数据的 Follower 会放弃收到的数据,Client 重新发送该写操作。
  4. commit通知发出后宕机:因为 commit 命令已发出,说明该写请求已被处理。