Raft-分布式系统一致性解决方案

此贴非原创,仅仅是楼主的学习笔记。原帖:https://www.jianshu.com/p/8e4bbe7e276c

目录

    • 针对简化版拜占庭将军问题,Raft 解决方案类比
    • Raft结点的状态
    • 选主 Leader Election
    • 1. 正常情况下选主
    • 2. Leader出故障之后,选新主
    • 3. 多个 Candidate情况下的选主
    • 复制日志 Log Replication
    • 1. 正常情况下复制日志
    • 2. Network Partition情况下的日志复制
    • 为什么Raft选主和同步日志都需要超过50%的结点同意?

针对简化版拜占庭将军问题,Raft 解决方案类比

拜占庭将军问题是分布式领域最复杂、最严格的容错模型。但在日常工作中使用的分布式系统面对的问题不会那么复杂,更多的是计算机故障挂掉了,或者网络通信问题而没法传递信息(信使被暗杀导致消息无法传递),这种情况不考虑计算机之间互相发送恶意信息(军中无叛军),简化了系统对容错的要求,最主要的是达到一致性。

Raft 的解决方案大概可以理解成 先在所有将军中选出一个大将军,所有的决定由大将军来做。
(1)选举环节:比如说现在一共有3个将军 A, B, C,每个将军都有一个随机时间的倒计时器,倒计时一结束,这个将军就会把自己当成大将军候选人,然后派信使去问其他几个将军,能不能选我为总将军?
(2)假设现在将军A倒计时结束了,A派信使传递选举投票的信息给将军B和C,如果将军B和C还没把自己当成候选人(倒计时还没有结束),并且没有把选举票投给其他,他们就会把票投给将军A,信使在回到将军A时,将军A知道自己收到了足够的票数(大于50%的将军数量),成为了大将军。
(3)在A成为大将军之后,是否要进攻就由大将军决定,然后派信使去通知另外两个将军,如果在一段时间后还没有收到回复(可能信使被暗杀),那就再重派一个信使,直到收到回复。

Raft结点的状态

从拜占庭将军回到分布式系统,每个将军相当于分布式系统中的一个结点。Raft方案中,分布式系统的结点一共有3钟状态:Follower、Candidate、Leader,每个结点有一个最重要的属性—倒计时器 (Election Timeout),时间随机在 150ms 到 300ms 之间。

在 Raft 运行过程中,最主要进行两个活动:
选主 Leader Election
复制日志 Log Replication

选主 Leader Election

1. 正常情况下选主

(1)假设现在有如图5个节点,5个节点一开始的状态都是 Follower。
Raft-分布式系统一致性解决方案_第1张图片
(2)5个结点的倒计时器开始计时,当第一个倒计时结束的结点产生后(Timeout),这个节点©的状态变成 Candidate 开始选举,它给其他几个节点发送选举请求 (RequestVote)
Raft-分布式系统一致性解决方案_第2张图片
(3)其它4个F结点都给C结点投票,C结点的状态由candidate变成了leader,并在每段时间就向它所有的Follower发送心跳Heartbeat以保持其状态。Follower收到心跳后倒计时器被重设。
Raft-分布式系统一致性解决方案_第3张图片
这是最简单的选主情况,只要有超过一半的节点投支持票了,Candidate 才会被选举为 Leader,5个节点的情况下,3个节点 (包括 Candidate 本身) 投了支持就行。

2. Leader出故障之后,选新主

(1)开始时已经有一个Leader,在指挥所有Follower工作。L的右上角的1表示该Leader的任期,1表示第一任Leader。
Raft-分布式系统一致性解决方案_第4张图片
(2)Leader 出故障挂掉了,其他四个 Follower 将进行重新选主。
Raft-分布式系统一致性解决方案_第5张图片
(3)由于Leader出了故障,不能及时发送Heartbeat到4个Follower,Follower的倒计时器则持续计时,直到第一个计时结束的结点出现。与上节选主的过程类似,倒计时结束的结点(C2)向其它3个结点发送投票邀请,其它结点倒计时没有结束,且没有向其他人投票,则它们均向该结点(C2)投票。(C2)结点成为新的leader。
Raft-分布式系统一致性解决方案_第6张图片
Raft-分布式系统一致性解决方案_第7张图片
(4)此时,挂掉的Leader恢复到了分布式系统中,Raft根据选举记录,重新加入的 Leader 是第一轮选举 (Term 1) 选出来的,而现在的 Leader 则是 Term 2,所有原来的 Leader 会自觉降级为 Follower。
Raft-分布式系统一致性解决方案_第8张图片
Raft-分布式系统一致性解决方案_第9张图片

3. 多个 Candidate情况下的选主

(1)假设分布式系统中有4个结点,有两个Follower同时Timeout,都变成了candidate发出选主请求,分别给一个 Follower 发送了投票请求。
Raft-分布式系统一致性解决方案_第10张图片
(2)两个 Follower 分别返回了ok,这时两个 Candidate 都只有2票(自己给自己投1票),要超过50%的Follower投票—至少3票才能被选成 Leader。 两个 Candidate 会分别给另外一个还没有给自己投票的 Follower 发送投票请求。
Raft-分布式系统一致性解决方案_第11张图片
(3)但是因为 Follower 在这一轮选举中,都已经投完票了,所以都拒绝了他们的请求。所以在 Term 2 没有 Leader 被选出来。
Raft-分布式系统一致性解决方案_第12张图片
(4)这时,两个节点的状态是 Candidate,两个是 Follower,但是他们的倒计时器仍然在运行,最先 Timeout 的那个节点会进行发起新一轮 Term 3 的投票。
Raft-分布式系统一致性解决方案_第13张图片
(5)两个 Follower 在 Term 3 还没投过票,所以返回 OK,这时 Candidate 一共有三票,被选为了 Leader。
Raft-分布式系统一致性解决方案_第14张图片

(6)如果 L3的Heartbeat 的时间晚于另外一个 Candidate timeout 的时间,另外一个 Candidate 仍然会发送选举请求。Raft-分布式系统一致性解决方案_第15张图片
(7)两个 Follower 已经投完票了,拒绝了这个 Candidate 的投票请求。
Raft-分布式系统一致性解决方案_第16张图片
(8)Leader 进行 Heartbeat, Candidate 收到后状态自动转为 Follower,完成选主。
Raft-分布式系统一致性解决方案_第17张图片

复制日志 Log Replication

Raft 在实际应用场景中的一致性更多的是体现在不同节点之间的数据一致性,**客户端发送请求到任何一个节点都能收到一致的返回,当一个节点出故障后,其他节点仍然能以已有的数据正常进行。**在选主之后的复制日志就是为了达到这个目的。

1. 正常情况下复制日志

(1)初始,Leader和所有Follower都没有任何数据。
Raft-分布式系统一致性解决方案_第18张图片
(2)客户端发送请求给 Leader,储存数据 “sally”,Leader 先将数据写在本地日志,这时候数据还是 Uncommitted (还没最终确认,红色表示)
Raft-分布式系统一致性解决方案_第19张图片
(3)Leader 给两个 Follower 发送 AppendEntries 请求,数据在 Follower 上没有冲突,则将数据暂时写在本地日志,Follower 的数据也还是 Uncommitted。
Raft-分布式系统一致性解决方案_第20张图片
(4)Follower 将数据写到本地后,返回 OK。Leader 收到后成功返回,只要收到的成功的返回数量超过半数 (包含Leader),Leader 将数据 “sally” 的状态改成 Committed。( 这个时候 Leader 就可以返回给客户端了)
Raft-分布式系统一致性解决方案_第21张图片
(5)Leader 再次给 Follower 发送 AppendEntries 请求,收到请求后,Follower 将本地日志里 Uncommitted 数据改成 Committed。这样就完成了一整个复制日志的过程,三个节点的数据是一致的。
Raft-分布式系统一致性解决方案_第22张图片

2. Network Partition情况下的日志复制

在 Network Partition 的情况下,部分节点之间没办法互相通信,Raft 也能保证在这种情况下数据的一致性。
(1)一开始有 5 个节点处于同一网络状态下。
Raft-分布式系统一致性解决方案_第23张图片
(2)Network Partition 将节点分成两边,一边有两个节点,一边三个节点。
Raft-分布式系统一致性解决方案_第24张图片
(3)上面的分区中, Leader 接收到客户端的数据 “bob” 并同步到 Follower。
Raft-分布式系统一致性解决方案_第25张图片
(4)上面的网络分区中,因为只有两个节点,Follower回复的ok少于3个节点,所以 “bob” 的状态仍是 Uncommitted。所以在这里,服务器会返回错误给客户端。
Raft-分布式系统一致性解决方案_第26张图片
(5)下面的 Partition 有三个节点,进行重新选主(超过50%)。客户端数据 “tom” 发到新的 Leader,同步到另外两个 Follower。
Raft-分布式系统一致性解决方案_第27张图片
(6)由于下面的 Network Partition的结点数量超过50%,因此可以将"tom"更新到commit状态。
Raft-分布式系统一致性解决方案_第28张图片
Raft-分布式系统一致性解决方案_第29张图片
(7)网络状态恢复,5个节点再次处于同一个网络状态下。但是这里出现了数据冲突 “bob" 和 “tom"
Raft-分布式系统一致性解决方案_第30张图片
(8)三个节点的 Leader 广播 Append Entries

Raft-分布式系统一致性解决方案_第31张图片
(9)两个节点 Partition 的 Leader 自动降级为 Follower,因为这个 Partition 的数据 “bob” 没有 Commit,返回给客户端的是错误,客户端知道请求没有成功,所以 Follower 在收到 AppendEntries 请求时,可以把 “bob“ 删除,然后同步 ”tom”,通过这么一个过程,就完成了在 Network Partition 情况下的复制日志,保证了数据的一致性。
Raft-分布式系统一致性解决方案_第32张图片
Raft-分布式系统一致性解决方案_第33张图片

为什么Raft选主和同步日志都需要超过50%的结点同意?

根据反证法,如果不需要超过50%的结点同意即可完成选主。那么在多个Candidate同时进行选主 / Network Partition的日志复制时,会产生多个主的情况 或 导致数据不一致。

你可能感兴趣的:(随笔)