RocketMQ前置:完全图解Raft协议基础

RocketMQ前置:完全图解Raft协议基础,第1张

学习链接🤔:https://raft.github.io/

官方动画演示😋:Raft (thesecretlivesofdata.com) (做得真的赞吼)

文章目录
  • 一、领导者选举 Leader Election
  • 二、日志复制 Log Replication
  • 三、网络分区 network partitions

以下图片都来自官方动画演示

Raft 是分布式领域中解决一致性的协议,主要包含领导者选举、日志复制两个部分。

Raft 协议中的每个节点(存储数据的数据库服务器)都会处于三种状态之一:

  • Leader 领导者
  • Follower 跟随者
  • Candidate 候选者
一、领导者选举 Leader Election

一开始所有的节点的状态都是 Follower 。现在要从这些 Follower 中选出一个 Leader,该怎么选呢?

这里先说明,在 Raft 中有两个控制选举的超时设置:

  • 选举超时 election timeout
  • 心跳超时 heartbeat timeout

(1)Election Timeout

Election Timeout 是Follower 等待成为 Candidate 的时间,被设置为150ms~300ms之间的随机值。

(2)Heartbeat Timeout
Heartbeat timeout 是 Leader 向 Follower 发送 Append Entries messages 后等待 Follower 响应的时间。

现在,节点 A 的 Election Timeout 超时了,它的状态从 Follower 变成 Candidate,开始了新的选举任期 term。它先投了自己一票,并向其他节点发送请求投票消息 Request Vote messages。

如果接收节点B、C 在这个任期内还没有投票,那么它们会投票给节点 A。并且重置其 Election Timeout。
如果节点A收到了超过半数的投票,那么节点A的状态就会从 Candidate 变成 Leader。这个机制保证了一个集群一个任期只能有一个Leader。

Leader 节点A 开始向 Follower 发送附加条目消息 Append Entries messages。

这些消息以 heartbeat timeout 指定的间隔发送,然后 Follower 来响应消息。

这个选举期限将会持续到某一个Follower节点停止接收心跳并成为候选人。重新选举发生,经过上述过程,产生新的 Leader 节点。

这个过程就叫做 领导者选举(Leader Election)。

但是如果有两个节点在相同任期中同时成为 Candidate,那么就有可能发生 分裂投票 split vote(同时产生多个候选者并且他们的投票数相同) 的情况,又该怎么选举 Leader 呢?

假如有两个节点A、B的 election timeout 同时超时成为Candidate,开始了新的选举任期 term,term 从3变成4。然后又都投了自己一票。

而且这两个节点都先于另一个节点到达一个 Follower 节点,也就是节点C先收到节点A的 Request Vote messages,节点D先收到节点B的 Request Vote messages,

现在节点A、B 都有 2 票,并且在这个任期内不能再获得更多投票了。那么这些节点将等待新的选举并重试。

假如重试到 term 为7的时候,节点 D在这个期间获得了多数票,因此它成为 leader。

二、日志复制 Log Replication

所有对系统的更改都要经过 Leader 来复制到所有节点上。这一切是通过之前 Leader Election 时用作发送心跳的 Append Entries message 来完成的。

现在客户端(绿色节点)发送一个消息给 Leader 节点A,要求更改系统的状态为”5“。现在这个更改并没有被提交,所以节点A的值还不是“5”。

这个更改作为一个条目 entry 被添加进Leader 的 log 中。

这个更改会在下一个心跳的 Append Entries message 中被 Leader 节点A 发给 Follower 节点B、C。一旦大多数 Follower 承认 entry ,节点A就会提交 entry 并发送响应消息给客户端。现在这个集群的值都是“5”,达成一致了。

这个过程就是日志复制(Log Replication)。

三、网络分区 network partitions

现在一共有五个节点,其中节点B、D是 Leader,其他都是 Follower。

让我们添加一个分区来将 A 和 B 与 C、D 和 E 分开,并添加另一个客户端,尝试更新两个Leader节点。
下面这个客户端尝试将节点 B 的值设置为“3”。

但是因为有分区的存在,节点 B 只能把这个 entry 复制到节点A,无法复制到多数(2 < 3),因此此 entry 保持未提交状态。
另一个客户端尝试将节点 D 的值设置为“8”。这将成功,因为它可以复制到多数(3 = 3 )。

现在让我们修复网络分区。
节点B的选举任期 term 没有节点D的高,节点B下台变成 Follower。

节点 A 和 B 都将回滚它们未提交的 entry 并匹配新 Leader 的 log。

现在我们的日志在集群中是一致的了。

欢迎分享,转载请注明来源:内存溢出

原文地址: https://outofmemory.cn/langs/877879.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-05-13
下一篇 2022-05-13

发表评论

登录后才能评论

评论列表(0条)

保存