两阶段提交
来自智得网
简介
两阶段提交(2PC)是分布式事务的一种实现方案。
两阶段提交协议把分布式事务分成两个过程,分别是准备阶段和提交阶段,准备阶段和提交阶段都是由事务管理器(协调者)发起,资管管理器(事务参与者)接收协调者的指令完成事务的执行动作。
两阶段具体分工如下:
准备阶段:协调者向参与者发起指令,参与者评估自己的状态,如果参与者评估指令可以完成,参与者会写redo或者undo日志(这也是前面提起的Write-Ahead Log的一种),然后锁定资源,执行操作,但是并不提交。
提交阶段:如果每个参与者明确返回准备成功,也就是预留资源和执行操作成功,协调者向参与者发起提交指令,参与者提交资源变更的事务,释放锁定的资源;如果任何一个参与者明确返回准备失败,也就是预留资源或者执行操作失败,协调者向参与者发起中止指令,参与者取消已经变更的事务,执行undo日志,释放锁定的资源。
原理
普通事务的提交也包括写数据阶段和提交阶段,例如Mysql的InnoDB引擎在提交之前,会写入undolog,修改BufferPool,在事务提交的时候会写入redolog。两阶段提交会将提交操作再分为两部分,例如准备提交的阶段会先准备写入redolog,之后写入binlog,再进行提交redolog。
准备阶段
- 两阶段事务的准备阶段,协调者会对所有的参与者发起准备的指令。
- 参与者接收到准备指令之后,进行事务操作,本环节的事务操作一般包括资源锁定,记录回滚日志(Undolog),执行成功会给协调者发送成功的返回,否则返回失败。
- 协调者收到所有参与者的返回都是成功时,而阶段提交会进入提交阶段。
- 协调者如果收到部分参与者的返回是失败的时候,则将成功的参与者进行回滚。
提交阶段
- 两阶段提交的提交阶段会完成事务中剩余的操作,并且释放资源。
- 如果两阶段提交进行回滚,则会将准备阶段的数据进行恢复操作。
- 当协调者收到所有参与者成功的指令,两阶段提交结束。
提交阶段如果部分参与者成功,部分参与者失败,仍然会出现分布式事务状态不一致的情况,但是因为主要的数据操作都是在准备阶段完成,所以提交阶段失败的概率较小。
应用
两阶段提交协议在准备阶段锁定资源能保证强一致性,但实现复杂、成本较高,不够灵活,还存在下列问题:
- 阻塞
- 两阶段提交中协调者发起的准备指令和提交指令必须收到所有参与者的返回才能决定后续的状态,否则将持续处于阻塞状态,此时占用的资源会被一直锁定,长期占据的资源会对性能有较大的影响。
- 协调者在执行事务的过程中如果发生故障,则所有的参与者都会陷入阻塞等待后续指令。
- 不一致
- 协调者发送提交指令,部分参与者成功提交了事务,部分参与者未能接受提交指令,此时多个参与者的状态就出现了不一致的情况。
- 如果部分参与者在接收到提交指令之后发生宕机,而此时协调者也发生了宕机,后续选举出来的协调者的继任者无法确定所有参与者的状态,此时会出现故障。