分布式一致性协议(三)

在上一篇文章中讨论了leader选举对于基本Paxos算法在实际工程应用中的必要性,这一篇文章首先结合raft的选举算法谈谈leader选举的实质和常用方法,然后结合raft算法选举后的日志恢复以及《Paxos Made Simple》里lamport勾勒的multi-paxos的日志恢复来详细分析一下选主后要做的两件重要事情以及俩算法在这块的差异。


1.raft的选主算法以及选主算法的实质

前面一篇文章中提到,选主本质上就是分布式共识问题,可以用基本Paxos解决,下面就raft选主算法与基本Paxos的对应关系来说明。

关于raft选主的详细描述可以参考原论文

  • raft选主时的term实际上对应基本Paxos中的proposal id
  • raft选主时的要求即每个term期间只能最多有一个leader实际上对应于基本Paxos的每个proposal要么达成决议要么没达成决议
  • raft选主时的随机timeout实际上是为了防止基本Paxos livelock的问题,这也是FLP定理所决定的
  • raft选举时与基本Paxos的区别在于,raft选举不要求在某个term(proposal id)选出一个leader(达成决议后)不需要后续的某个term(proposal id)选出同一台机器作为leader(使用同一个值达成决议),而是可以每次重新选一个机器(proposal选不同值),当然我们可以使用一定方法,增大选某台机器的概率,比如为每台机器设置rank值。
  • raft选举时,当candidate和leader接受到更大的term时立即更新term转为follower,在下一次超时前自然不能再提proposal,实际上对应于基本Paxos第一阶段acceptor接收到proposal id更大的proposal时更新proposal id放弃当前的proposal(在选主中实际上就对应放弃我candidate和leader的身份,本质上就是proposer的身份)

所以选主本质上是可以通过基本Paxos算法来保证的,选主没有完全使用Paxos算法,可以看作使用了Paxos算法的某个子算法解决了比容错分布式一致问题限制稍微小的问题。当然,我们可以在选主时加上额外的限制条件,只要能保证可能选出一个主。


2.选主后日志的同步

选出新的leader后,它至少要负责做两件事情,一件是确定下一次客户请求应该用哪个日志槽位或者说项,另一件是确定整个集群的机器过去已经提交过的最近的项(或者说日志),确定这两个值的过程实际上就是日志恢复的过程,下面对两种算法具体分析。这里补充一点之前文章漏掉的东西,基本Paxos算法实际上有三个阶段,最后一个阶段是提交阶段,只是通常leader-based算法为了优化网络开销,将第三阶段和第二阶段合并了,而在每次执行第二阶段是带上leader已经提交过的日志号,所以新leader还需要确定最近被提交过的日志,而这种优化也引入了另外的复杂性。

  • 对于raft来说

    • 由于选主时额外的限制条件以及log replication时的consistency check保证(关于这两者是什么东西,不细说,基本上这就是raft简化了multi-paxos最核心的东西吧),所以每个新leader一定有最新的日志,所以对于下一条日志槽位的选取,只需要读取最后一条日志来判断就行了。关于raft的log replication,后面有机会再说。

    • 而对于已提交日志的判断,由于存在可能已经形成多数派,也就是在内存中形成了多数派,但是还没有机器commited到磁盘,这时,新的leader无法判断这条日志是已经提交还是没有提交(参见原论文5.4.2节),raft的做法是不管这条可能被新leader覆盖掉的日志,只需要保证在新的term期间,提交一条日志,那么由于consistency check,自然会提交之前的日志。

  • 对于multi-paxos来说

    • 由于在log replication说,不像raft那样保证一个顺序应答(不能保证线性一致性,能保证顺序一致性),也就是保证一个日志槽位达成多数派后才接受下一个请求,multi-paxos可以在一个日志槽位还没有达成多数派时并发处理另外一个日志槽位,所以新leader在恢复确认下一个可用日志槽位以及已提交日志时更麻烦。

    • lamport原论文描述的方法是,对于明确知道已提交的日志(这一点我们可以通过给每一条已提交日志加一个标示,这样可以减少日志恢复的时间),不用再次进行基本Paxos的决议,而对于未明确知道已提交的日志,则进行基本Paxos的二个阶段来确认已达成多数派的值,对于中间空洞且之前没有达成过多数派的,直接写一条空操作的日志,至于为什么会产生这种情况,可以参考原论文。一旦所有日志都经过这种方法恢复后,下一个可用日志槽位和最近已提交日志号也就能确定了。

对比上面两者恢复的过程,我们可以看到raft是怎么简化multi-paxos的。一旦新的leader确定了上面那两件事情,就可以进入正常的log replication阶段了,也就仅仅是多数派的事情了。


3.log replication,客户端交互,membership管理,leader lease等

这一节为后面的文章做个铺垫,对于log replication实际上不会涉及太多状态的reason,所以也就比较容易理解,基本上是类似简化的两阶段提交,后面会介绍下raft的log replication。对于客户端交互,leader什么时候返回结果,客户端怎么超时重试,以及怎么保证请求的幂等,membership management,以及leader lease等一些优化手段。

comments powered by Disqus