渐行渐远渐无书
水阔鱼沉何处问
前几天的一篇文章已经讲过了拜占庭将军问题,从而引出了分布式的一致性问题,Raft正是一种以较易理解的方式解决该问题的算法。
说实话,我这几天看了Raft的英文,也看了Raft的中文译文版,然后又找了很多大佬的博文看了,实在没觉得Raft容易理解或者是容易实现,如果真要自己实现的话还真的一头雾水,当然看懂讲的什么东西还是不难的。
Raft通过一种少数服从多数的选举方式确定一个高贵牛逼的领导人,在任期内,其他群众均要接受来自他的管理(心跳和日志复制),当然最重要的还是保持整个集群的一致性。
每个结点有三个状态(角色):
- 领导人
- 候选人
- 群众
为了达到一致性,可以将整个问题分解成如下三个子问题:
- 领导选举:一个新的领导人需要被选举出来,当现存的领导人宕机的时候。
- 日志复制:领导人必须从客户端接收日志然后复制到集群中的其他节点,并且强制要求其他节点的日志保持和自己相同。
- 安全性::如果有任何的服务器节点已经应用了一个确定的日志条目到它的状态机中,那么其他服务器节点不能在同一个日志索引位置应用一个不同的指令。
这里会简要介绍前两个问题,第三个问题会在下面几篇博文里慢慢提到。
领导选举
最开始的领导人由一次大选选出,初始状态下,所有参与者都是群众。大选开始的时候,所有群众都会开始随机倒计时,只要倒计时结束,该群众就会变身为候选人,然后向集群内所有其他参与者发送“你投我吧”,如果参与者身份仍然是群众,就会给出自己的选票(只有一张哦),如果不是群众,则拒绝。可以想象到的是,因为要多数选票才能任选,所以最后一定会有领导人产生,然后其他所有候选人变为群众,接受领导。
整个过程用图来描述的话就和上图差不多。
日志复制
一个领导人选举出来以后,就开始为客户端提供服务了(直接给客户端提供服务的是领导人节点)。客户端发送的每次请求都会变成一条条日志条目,然后被增加到日志中,然后并行地发起AppendEntries RPC给每个群众,从而到达日志复制的目的。这里每次远程地交互都会有“超时重传”来保障一致性和可靠性。领导人在收到大部分群众的确认后,会将执行结果返回给客户端,当然后面领导人会不断尝试将日志条目增加给未确认的群众节点(AppendEntries RPC),直到整个集群达到一致性。
以上提到的(AppendEntries RPC)会在后面的博文中讲述。
注:本文中用到两种图来源于文章Raft 为什么是更易理解的分布式一致性算法