概念
在一个分布式系统中,每个节点有知道自己是否能力处理事务及事务处理结果,然而却无法直接获取其他节点的事务处理结果。
当一个事务需要跨节点处理的时候,为了保证事务处理的 ACID 特性,就需要一个协调者的角色来统一调度所有分布式节点的执行逻辑。那些被调度的分布式节点则称为参与者。
协调者负责调度参与者的行为,并最终决定这些参与者是否要真正地完成事务的提交。
而基于以上思想,衍生出了二阶段和三阶段提交协议。
- pc: phase commit
- 2pc:需要经历两个阶段完成分布式事务的提交
- 3pc:需要经历三个阶段完成分布式事务的提交
2pc 协议
结合现实中的一个场景,好理解下:
这跟开发一个交付项目道理是一样的,你们项目团队接收到一个项目,项目经理作为协调者,会想团队成员询问一些列的问题,比如需求分析,可行性分析、开发项目,完成交付。
各个阶段都可能出现各种各样的问题,导致项目验收交付失败。
- 阶段一:项目经理(协调者)问你:能不能做?你们回答:能。
- 阶段二:项目经理发出立即实施的指令,你门接收到该指令,然后吭哧吭哧地完成整个项目的研发和交付,并告知项目经理,完成整个项目,项目周期结束。
2pc 的第一阶段,向各个参与者询问提交事务(发起询问)
- 协调者向各个参与者发送事务提交内容,询问是否可以执行事务提交操作,并开始等待所有参与者的反馈(响应)。
- 参与者收到请求,执行事务提交操作,将 Undo 和Redo 信息写入事务日志中,并向协调者反馈事务问询的结果(Yes or No)。
2pc的第二阶段,发起执行事务提交的请求(发起执行)
假设协调者接受到所有参与者的Yes 响应后,则会再次发起一个提交事务的请求,让参与者开始真正地执行事务提交。
3pc 协议
结合现实中的一个场景,好理解下:
这跟开发一个交付项目道理是一样的,你们项目团队接收到一个项目,项目经理作为协调者,会想团队成员询问一些列的问题,比如需求分析,可行性分析、开发项目,完成交付。
各个阶段都可能出现各种各样的问题,导致项目验收交付失败。
- 阶段一:项目经理(协调者)问你:能不能做(canCommit)?你们做了一个可能性分析后,觉得都觉得自己能做,然后回答:能。
- 阶段二:项目经理那你们准备下把它做了(preCommit),你们开始演练(不恰当的说,比如搞个 POC)整个过程,并告指挥中心,演练结束,可以立即实施。
- 阶段三:项目经理发出立即实施的指令,你门接收到该指令(doCommit),然后吭哧吭哧地完成整个项目的研发和交付,并告知项目经理,完成整个项目,项目周期结束。
下面以各阶段都成功的情况下,分别说明三阶段。
3pc 第一阶段:询问参与者,你们是否可以
该阶段主要完成的任务是:协调者想知道各个参与者能否顺利完成事务的处理,结果为协调者知道。相当于一次握手。
- 协调者发出事务问询:协调者向所有参与者发出一条包含事务内容的 canCommit 请求,询问是否可以执行事务操作。
- 参与者反馈事务问询:所有参与者收到来自协调者的事务问询后,正常情况下,如果自己可以顺利执行事务,则反馈Yes 响应给协调者;否则,反馈 No 响应。
正常的流程图如下:
3pc 第二阶段:告知参与者,你们都可以
该阶段完成了主要任务:基于协调者已知道,各个参与者也知道彼此(其他参与者)都能顺利完成事务提交任务。
假设协调者,收到了全部的 Yes 响应,则可以进行预提交阶段。
这个阶段,不再啰嗦,就是协调者告知所有参与者,你们都能完成此次提交任务。即所有对象(协调者和参与者都知道所有人都可以顺利完成事务的提交)。这点是个人目前认为是 3pc和 2pc 的核心区别:所有参与者都知道彼此能顺利完成事务提交。
3pc 第三阶段:参与者知道彼此都可以,然后执行事务提交
该阶段完成了主要任务是:基于协调者和参与者都已知道,各个参与者也知道其他参与者也都能顺利完成事务提交任务。进而要执行事务提交,完成分布式事务的提交。
此阶段,是在所有参与者已收到 preCommit 请求之后的逻辑,即使这个时候协调者挂了,也不影响后续参与者进行事务提交,这就规避了单点故障的问题。
2pc 与 3pc 优劣
- 在 2pc 协议中,可以概括为
c :“能不能做?”
p:“能”
c:“开始做”
p:“好……做完了” - 在 3pc 协议中,可以概括为
c :“能不能做?”
p:“能”
c:“准备去做”
p:“好,准备好了”
c:“开始做”
p:“好……做完了”
经过上面的分析,发现,3pc没有比 2pc 有什么特别明显的优势,唯一区别就是有一个预提交阶段。
若非要说该阶段算什么优点的话,我认为预提交阶段标示着参与者也知道彼此能够完成事物的提交。
对比之下,感觉 3pc 协议有些鸡肋,不觉得 3pc 相对 2pc有什么显著地优越性。