分布式一致性算法:Raft

分布式系统Raft节点三状态:

  • Follower
  • Candidate
  • Leader

节点倒计时:

  • 每个节点上都有一个倒计时器 (Election Timeout),时间随机在 150ms 到 300ms 之间。有几种情况会重设 Timeout:
    1. 收到选举请求
    2. 收到Leader的Heartbeat

Raft主要活动:

  • 选主 Leader Election
  • 复制日志 Log Replication

选主 Leader Elecation

正常情况下选主

背景:五个节点,一个Candidate,四个Follower。

  1. 在一个节点倒计时结束,节点变为Candidate节点。Candidate向其他四个Follower发送选举请求
  2. 四个Follower返回成功
  3. Candidate状态变为Leader,并在每个一小段时间后,就给所有的 Follower 发送一个 Heartbeat 以保持所有节点的状态,Follower 收到 Leader 的 Heartbeat 后重设 Timeout。

超过一半节点投支持票,Candidate就会被选举为Leader。5个节点的情况下,3个节点 (包括 Candidate 本身) 投了支持就行。

Leader出故障情况下选主

背景:五个节点,一个Leader,四个Follower

  1. Leader出故障挂掉,其他四个Follower重新选主。
  2. 四个Follower与在正常情况下选主流程一样,选出Leader。

之前故障的Leader恢复了,又重新加入:

  1. 在Raft中,第几轮选举是有记录的,重新加入的Leader是第一轮选举(Term 1)选出来的,而现在的Leader是Term 2 选出来的,因此所有原来的Leader会自觉降为Follower。

多个候选人情况下的选主

背景:四个节点,四个Follower。

  1. 两个Follower同时Timeout,都变成了Candidate,分别给一个Follower发送了投票请求。
  2. 两个Follower返回成功,此时两个Candidate都只有2票,要3票才能成为Leader。
  3. 两个Candidate分别向另一个还没有给自己投票的Follower发送投票请求。
  4. 因为两个Follower在这一轮中已经投完票了,因此拒绝了Candidate的请求。所有在Term2没有Leader被选出来。
  5. 这时,两个节点的状态是 Candidate,两个是 Follower,但是他们的倒计时器仍然在运行,最先 Timeout 的那个Candidate节点会进行发起新一轮 Term 3 的投票。
  6. 在Term3中,最新Timeout的节点成为唯一的Candidate,发起投票,其他两个Follower节点全部返回OK,此时Candidate有三票被选举成为Leader。
  7. 如果 Leader Heartbeat 的时间晚于另外一个 Candidate timeout 的时间,另外一个 Candidate 仍然会发送选举请求。两个 Follower 已经投完票了,拒绝了这个 Candidate 的投票请求。
  8. Leader 进行 Heartbeat, Candidate 收到后状态自动转为 Follower,完成选主。

复制日志 Log Replication

  • Raft在实际应用场景中的一致性更多的是体现在不同节点之间的数据一致性。
  • 客户端发送请求到任意一个节点都能收到一致的返回。
  • 当一个节点故障后,其他节点仍然能以已有的数据正常进行。

复制日志就是为了达到以上的目的。

正常情况下复制日志

背景:一个Leader,两个Follower

  1. Leader以及Follower无数据
  2. 客户端发储存数据的请求给Leader,Leader将数据写在本地日志,数据状态为 Uncommitted
  3. Leader给两个Follower发送AppendEntries请求,Follower将数据暂时写在本地日志,返回OK给Leader,数据状态为 Uncommitted
  4. Leader收到Follower的OK返回,只要收到的OK数量超过半数(包含Leader),Leader将数据状态修改为 Committed(此时Leader可以返回给客户端)。
  5. Leader再次给Follower发送AppendEntries请求,Follower收到请求将数据状态修改为Committed
  6. 完成复制日志过程,三个节点数据是一致的。

Network Partition 网络隔断情况下进行复制日志

背景:在Network Partition情况下,部分节点无法通信。五个节点,Network Partition将五个节点分为两边,一个两个节点partition1(两个节点中有Leader),一个三个节点partition2。

  1. 两个节点partition1中有Leader,Leader将来自客户端的数据同步给网络中的另外一个Follower节点。因为该网络因网络隔断只有两个节点,所以数据状态还是为 Uncommitted,服务端返回错误给客户端。
  2. 三个节点partition2进行重新选主,选出了一个Leader。
  3. 客户端数据发送到partition2的新的Leader,新Leader将数据同步给另外两个Follower,这个Partition有三个节点,超过半数,数据状态可以更改为 Committed

网络状态恢复,5个节点再次处于同一个网络状态下。但是这里出现了数据冲突。partition1和partition2的数据不一致。

  1. partition2的Leader广播AppendEntries,partition1的Leader自动降级为Follower
  2. 因为paratition1的数据没有Committed,返回给客户端的是错误,所以Follower在收到partition2的Leader的AppendEntries请求时,可以把Uncommitted的数据删除,同步Committed的数据。

通过以上过程,完成了Network Partition情况下的复制日志,保证了数据的一致性。

总结

  • Raft 是能够实现分布式系统强一致性的算法,每个系统节点有三种状态 Follower,Candidate,Leader。

  • 实现 Raft 算法两个最重要的事是:选主和复制日志

posted @ 2023-02-03 11:34  KbMan  阅读(63)  评论(0编辑  收藏  举报