计算机技术发展到现在,许多基础的技术实际上依旧处于无法保证绝对正确的状态。例如搜索分布式锁,网上全是使用redis实现分布式锁,文末的总结也是使用redis实现分布式锁存在各种各样的缺点。在分布式事务中,两阶段提交也存在明显的问题,可以依旧被拿出来讨论。在自然语言中,缺少评价生成文本的质量的方法,竟然使用BLEU。

两阶段和三阶段提交 在分布式系统中,各个节点之间在物理上相互独立,通过网络进行沟通和协调。
典型的比如关系型数据库,由于存在事务机制,可以保证每个独立节点上的数据操作可以满足ACID。
但是,相互独立的节点之间无法准确的知道其他节点中的事务执行情况,所以两台机器理论上无法达到一致的状态。

如果想让分布式部署的多台机器中的数据保持一致性,那么就要保证在所有节点的数据写操作,要不全部都执行,要么全部的都不执行。
但是,一台机器在执行本地事务的时候无法知道其他机器中的本地事务的执行结果。所以节点并不知道本次事务到底应该commit还是 roolback。

所以实现分布式事务,需要让当前节点知道其他节点的任务执行状态。常规的解决办法就是引入一个“协调者”的组件来统一调度所有分布式节点的执行。著名的是二阶段提交协议(Two Phase Commitment Protocol)和三阶段提交协议(Three Phase Commitment Protocol)。

1.二阶段提交协议

Two Phase指的是Commit-request阶段Commit阶段。

请求阶段 在请求阶段,协调者将通知事务参与者准备提交或取消事务,然后进入表决过程。 在表决过程中,参与者将告知协调者自己的决策:同意(事务参与者本地作业执行成功)或取消(本地作业执行故障)。

提交阶段 在该阶段,协调者将基于第一个阶段的投票结果进行决策:提交或取消。 当且仅当所有的参与者同意提交事务协调者才通知所有的参与者提交事务,否则协调者将通知所有的参与者取消事务。参与者在接收到协调者发来的消息后将执行响应的操作。
可以看出,两阶段提交协议存在明显的问题:

  • 同步阻塞 执行过程中,所有参与节点都是事务独占状态,当参与者占有公共资源时,第三方节点访问公共资源被阻塞。
  • 单点问题 一旦协调者发生故障,参与者会一直阻塞下去。
  • 数据不一致性 在第二阶段中,假设协调者发出了事务commit的通知,但是因为网络问题该通知仅被一部分参与者所收到并执行commit,其余的参与者没有收到通知一直处于阻塞状态,这段时间就产生了数据的不一致性。

三阶段提交协议

Three Phase分别为CanCommit、PreCommit、DoCommit。

三阶段提交协议和两阶段提交协议的不同

对于协调者(Coordinator)和参与者(Cohort)都设置了超时机制(在2PC中,只有协调者拥有超时机制,即如果在一定时间内没有收到cohort的消息则默认失败)。 在2PC的准备阶段和提交阶段之间,插入预提交阶段,使3PC拥有CanCommit、PreCommit、DoCommit三个阶段。 PreCommit是一个缓冲,保证了在最后提交阶段之前各参与节点的状态是一致的。

Paxos算法的提出

二阶段提交还是三阶段提交都无法很好的解决分布式的一致性问题,直到Paxos算法的提出,Paxos协议由Leslie Lamport最早在1990年提出,目前已经成为应用最广的分布式一致性算法。

无论是二阶段提交还是三阶段提交都无法彻底解决分布式的一致性问题。Google Chubby的作者Mike Burrows说过, there is only one consensus protocol, and that’s Paxos” – all other approaches are just broken versions of Paxos. 意即世上只有一种一致性算法,那就是Paxos算法。

Google Chubby的作者Mike Burrows说过这个世界上只有一种一致性算法,那就是Paxos,其它的算法都是残次品。

raft算法

raft算法可以看做是paxos算法的工程实现。