分布式存储引擎大厂实战:一文搞懂Raft系列(一)

分布式存储引擎大厂实战:一文搞懂Raft系列(一)

背景

  在现实的分布式系统中,不可能保证集群中的每一台服务器都是100%可用可靠的,集群中的任何机器都可能宕机、网络连接等问题导致集群中的某个结点不可用,这样,那个节点的数据就有可能和集群的不一致,所以需要一种机制来保证在大多数机器都存在的情况下向外提供可靠的数据服务。raft算法就是一种在分布式系统中解决集群中多节点之间数据一致性的算法。比如Golange生态圈的大名鼎鼎的etcd就是使用了Raft来实现的。掌握了这个算法,可以得心应手地处理绝大部分场景的容错和一致性需求。比如分布式配置系统,分布式NoSQL存储等等,轻松地突破系统的单机限制。

Raft算法介绍

  Raft算法是属于Multi-Paxos算法,它在兰伯特Multi-Paxos思想的基础上做了一些简化和限制,比如增加了日志必须是连续的,只支持领导者、跟随者和候选者三种人状态。从本质上来说Raft算法维持数据一致性的核心思想很简单,就是“少数服从多数”。
  Raft算法中除了领导者,还支持其它两种成员身份(服务器状态)分别是跟随者(follower)、候选人(candidate)。在任何时候,每一个服务器节点都处于这3个状态中的一个。

  • 跟随者(follower):相当于普通群众,默默地接收和处理来自领导者的消息,当领导者心跳超时的时候,它就会主动站出来,推荐自己当候选人。
  • 候选人(candidate):将向其他节点发送请求投票(RequestVote)RPC消息,通知其他节点来投票,如果赢得了大多数选票,就晋升位领导者。
  • 领导者(leader):不讲道理的霸道总裁,平常的主要工作内容就是3部分,处理写请求、管理日志复制和不断地发送心跳信息,通知其它结点“我是领导者,不要发起新的选举”。

领导者选举

  为了保证数据的一致性,最好的方式就是只有唯一的一个节点,唯一的这个节点读或者写,这样数据肯定是一致的;但是分布式架构显然不可以一个节点,于是Raft算法提出在集群的所有节点中选举中领导者,节点的领导者选举和现实生活中的选举十分相似,就是投票,集群中获票数最多的那个,就是领导者。为了防止出现平局的情况,一般在部署节点的时候,会将节点个数设置为奇数(2n+1)。这些节点是如何选举的呢?我们来看下面这个例子
在集群中,有三个节点A、B、C
在这里插入图片描述
  初始状态下,它们都是跟随者的状态,而没有领导者状态。过了一段时间A变成了候选者,这是开始选举了。为啥A能变成候选者呢,因为集群中每个节点都有一个等待超时时间,这里每个节点等待领导者节点心跳信息的超时时间间隔都是随机的,这里就是150ms~300ms的一个随机数,每当节点的等待超时时间到了就会触发它成为候选者。所以,A的等待超时时间最小(150ms),它会最先因为没有等到领导者的心跳信息,发生超时。
  每个节点中还有一个字段叫任期编号(term),这个term是一个全局的、连续递增的整数,每进行一次选举,term就会加一。这个时候,A触发了选举,它就增加自己的term,并推举自己为候选人,先给自己投上一票,然后向其他节点发送请求投票RPC消息,请它们选举自己为领导者。
在这里插入图片描述

  当B、C接收到候选人A的请求投票RPC消息,在term为1的这届任期内目前也还没有进行过投票,那么它将把选票投给节点A,并增加自己的term。

在这里插入图片描述
  如果候选人在选举超时时间内赢得了大多数选票,它将成为本届任期内新的领导者。节点A当选领导者后,它将周期性地发送心跳信息,通知其它服务器我是领导者,阻止跟随者发起新的选举。B和C收到心跳消息后,会重置election timout。心跳检测时间很短,要远远小于选举超时时间election timout。
在这里插入图片描述
B和C收到心跳信息后,会发送心跳响应并重置election timeout。
在这里插入图片描述

假设A发送的心跳检测信息由于延迟、丢包等B、C中的某个跟随者。而这个时候这个节点刚好election timeout,则触发自身选举。比如,此时C修改自身的任期编号term为2,自身状态变为候选者,并且投了自身一票。发起选举。
在这里插入图片描述
这时候C的term值变为2大于A的值,在Raft协议中,但凡收到任期编号值大于自己的节点,则会更改自身的值后,切换为跟随者,并重置自己的election timeout。

节点间通信

  在Raft中,服务器节点间的沟通采用是远程过程调用(RPC),在领导者选举中,需要用到两类RPC。

  • 请求投票RPC(RequestVote)RPC:是由候选人在选举期间发起通知各节点进行投票
  • 日志复制(AppendEntries)RPC:由领导者发起,用来复制日志和提供心跳信息。日志复制RPC只能由领导者发起。
      在Raft中约定,如果一个候选人或者领导者发现自己的任期编号比其他节点小时,它会立即恢复成跟随者状态。比如分区错误恢复后,term为3的领导者节点B,收到来自新领导者的,包含term为4的心跳信息,那么节点B将立即恢复成跟随者状态。
      此外,如果一个节点接收到一个包含较小的term值的请求,那么它会直接拒绝这个要求。比如节点C的term为4,收到包含term为3的请求投票RPC消息,那么它会拒绝这个消息。

选举规则

  1. 领导者周期性地向所有跟随者发送心跳信息(不包含日志项的日志复制RPC消息),通知大家自己是领导者,阻止跟随者发起新的选举

  2. 如果在指定时间内,跟随者没有接收到来自领导者的消息,跟随者没有接收到来自领导者的消息。那么它就认为当前没有领导者,推举自己自己为候选人,发起领导者选举

  3. 在一次选举中,赢得大多数选票的候选人晋升为领导者。

  4. 在一次选举中,每一个服务器节点最多会对一个term投出一张选票,并且按照“先来先服务”的原则进行投票。比如节点C的term为3,先收到了1个包含term为4的来自节点A投票请求。然后又收到了来自B的term为4的投票请求,那么节点C将会把唯一一张选票投给A,当再收到节点B的投票请求RPC消息时,已经没有票可以投了。
    在这里插入图片描述

  5. 日志完整性高的跟随者拒绝投票给日志完整性低的候选人。比如节点B的term为3,节点C的term为4,节点B的最后一条日志项对应的term为3,而节点C为2。此时节点C请求B投票给自己将会被拒绝。

随机超时时间

  1. 跟随者等待领导者心跳信息的时间间隔是随机的
  2. 如果候选人在一个随机时间间隔内,没有赢得过半票数则选举无效,然后候选人发起新一轮选举。等待选举超时的时间间隔在这里也是随机的。

总结

  • Raft算法通过任期、领导者心跳信息、随机选举超时时间、先来先服务的投票原则等,保证了一个任期内只有一个领导,这也极大地减少了选举失败的情况。
  • Raft算法和Multi-Paxos不同之处在于不是所有节点都能当选领导,只有日志完整的节点才能当选节点。而且日志还必须是连续的。

猜你喜欢

转载自blog.csdn.net/songguangfan/article/details/115055366