Paxos算法将分布式系统中的节点分为提案节点、决策节点和记录节点。
提案节点:称为Proposer。这种节点的作用是针对某个值提出设置,这种行为就是Proposal。而提案一旦成功,即值设置成功,就不会丢失也不可变。
决策节点:称为Acceptor。这种节点是应答提案的节点,决定该提案是否可被投票、是否可被接受。提案一旦被半数的决策节点所接受,就要被所有的决策节点Accept。提案被通过之后,就意味这该值不可以被修改,同时要被所有节点接受。
记录节点:称为Learner。这种节点不参与提案与决策,只是记录在提案、决策节点中已经达成共识的记录。
系统内部每个节点之间的通讯是不可靠的。每个节点收到的消息有可能延迟、丢失,但是不会出现消息传递错误的情况。
系统外部是可以进行并发访问的。如果只有一个用户进行串行的访问时,采用Quorum机制,即少数服从多数。就可以保证值可以被正常的读写。
准备阶段相当于抢占锁的阶段,当提案节点准备发起提案时,会先向每个节点广播一个准备请求,并且准备请求中会携带一个PID(提案ID)。决策节点收到之后,会返回给提案节点两个'承诺'和一个'应答'。
当提案节点收到多数决策节点的应答之后,就会开始'批准(Accept)'阶段。这时会有两种结果:
如果提案节点发现所有响应的决策节点此前都没有批准过这个值(即为空),就说明它是第一个设置值的节点,可以随意地决定要设定的值;并将自己选定的值与提案 ID,构成一个二元组 (id, value),再次广播给全部的决策节点(称为 Accept 请求)。 如果提案节点发现响应的决策节点中,至少一个节点的应答中包含有值了。则必须无条件的从应答中找出提案ID最大的那个值并接受,构成一个二元 (id, maxAcceptValue),然后再次广播给全部的决策节点(称为 Accept 请求)。
当决策决点收到Accept请求后,会在不违背以前的承诺的前提下,接收并持久化当前提案ID和提案要设定的值。如果违反此前作出的承诺,即收到的提案 ID 并不是决策节点收到过的最大的,那允许直接对此 Accept 请求不予理会。
当提案节点收到了多数决策节点的Accept应答后,协商结束,将共识后的决议结果发送给记录节点进行学习。整个过程的时序图如下:

到这里我们就对分布式共识算法Paxos有了一定的认识,Paxos算法并不是完美的,由于其每个节点都是可能发出准备请求的,所以是会出现活锁的情况,即两个提案节点互不相让地提出自己的提案,抢占同一个值的修改权限,导致整个系统在持续性地“反复横跳”,从外部看就像是被锁住了。
为了解决Paxos算法中'活锁'的问题,但是又不破坏众节点平等的原则。所以提出了在提案节点中区分主次,限制只有主提案节点才可以进行提案。并且增加了选主的过程,在主提案节点宕机时可以从提案节点中选出主提案节点。
通过这种方案解决了并发的问题,这样可以使得每次提案都是串行的方式进行发起。
Raft算法主要是针对简化版的拜占庭将军问题做了处理。即在网络分区的情况下,出现了双主节点的情况,这时只要有一个分区中有超过半数的节点,这样分布式系统就仍然可以运行。
当然对于另一分区中主节点的提交记录,当网络恢复之后,将自己的提交记录回滚,并获取到主节点的提交记录,然后在自己本地提交,这时完成数据的同步,保证数据一致性。




