raft共识协议

raft是一个基于选主、复制的共识协议。集群中的节点分为领导者、候选者和跟随者三种,99%的时间内,都是只有领导者和跟随者。领导者接受客户端请求、自己做决定,然后同步给所有跟随者。当大多数的跟随者回复同意之后,就认为这个决议被提交了,领导者可以更新这个决议到自己的日志里面,后续状态机可以按照日志执行。
raft包括两个流程,一个是选主,一个是日志复制。当网络正常、节点正常的时候,一直只需要走日志复制流程。当领导者挂掉之后才会走选主流程。这个比较容易理解,但是为了保证协议的正确,raft在上述流程加入了很多限制或者约束,在raft中,这些约束单独放到safe章节进行描述。

term

这个是最重要的概念,是基于逻辑时钟实现的序列号,用于确定日志的顺序,在后续的选主和日志复制中,需要大量使用。
所有节点维护同一个term。在所有的rpc通讯中,都包括这个term,用于同步更新,也负责一些判断,比如一个领导者或者候选人收到一个term更高的消息,那么它会立即放弃领导者角色,变成跟随者。

选主

选主采用随机超时的机制,即为不同的节点设置不同的超时参数,一般设为100-300ms之间,每个机器不同。这个时间要大于网络传输时间,所以根据实际网络情况需要配置。选主的流程很简单,就是任何节点在一定时间内没有收到领导者的消息后,就把自己变为候选者,将term++,发送RequestVote消息,当收到大多数的同意回复后,就认为自己是领导者,开启一个新篇章,进入日志复制阶段。

日志复制

日志复制也很简单。客户端可以向集群中的任何节点发送请求,跟随者收到后,会拒绝该请求并把领导者的信息发给客户端,客户端连接领导者发送请求。领导者收到请求后,向所有的跟随者发送AppendLog消息,当收到大多数的回复后,即认为该请求已经被commited,然后将改请求插入到状态机日志中。

安全

上述流程是正常的流程,可以简单感觉到,如果发生网络或节点错误,上述流程无法保证协议的安全性。在上述流程的框架下,对领导者、候选者和跟随者有一些约束,来保证协议的安全性。

  1. term在全局维护。在AppendLog和RequestVote消息中,都需要携带term。term的含义类比paxos的序列号。当节点收到任何消息后,判断:如果大于本地term,更新本地term,如果等于本地term,正常执行;如果小于本地term,返回拒绝。发送节点一旦收到拒绝消息后,立刻变为更随着。
  2. 单项流动。跟随者处于被动模式,绝不主动发消息。领导者和候选者是主动模式,分别发送AppendLog和RequestVote消息。
  3. 领导者独裁。领导者绝不更新本地的日志,所有的决定也是有领导者确定。
  4. 选主谨慎。由于领导者有很大的权威,所以选主要求领导者一定是集群中日志最全的那个候选人。具体做法是,当其他节点收到候选人的选主请求后,后比较候选人和自己的term,如果本地term大于候选人,则返回拒绝。由于我们采用大多数策略, 大多数的节点的term应该是一致的,所以对于缺少日志(即term小的)的候选人是无法获得领导者地位的。

おすすめ

転載: blog.csdn.net/wlstephenw/article/details/123115995
おすすめ