两阶段提交(Two-Phase Commit)

两阶段提交

两阶段提交是一种同步协议,是计算机网络尤其是在数据库领域内,为了使基于分布式系统架构下的所有节点在进行事务处理过程中保持原子性和一致性而设计的一种算法。

两阶段提交的执行过程

在两阶段提交过程中,主要分为了两种角色协调者(coordinator)和参与者(participants),协调者主要就是起到协调参与者是否需要提交事务或者中止事务,参与者主要就是接受协调者的响应并回复协调者是否能够参与事务提交,当接受到协调者提交事务的命令后提交事务等功能。

无故障两阶段执行流程

举例来描述,假如现在有一家电脑组装店,店里就一个老板(协调者),电脑组装的主板来自主板供货商(参与者),CPU来自CPU供货商(参与者),内存条来自内存条供货商(参与者)。每当一个顾客来店里购买电脑时,顾客会说出自己想要的配置,比如两个主板、四颗CPU和两条1G内存条,此时老板就需要分别向三家供货商去询问是否有足够的货源,如果每个供货商都回答说有足够的货,此时老板就知道这个电脑可以组装成功,然后就跟顾客反应可以做成,是否需要下单,顾客说好下单,此时老板就跟各个供货商下单,然后各个供货商就把货发送过来。此时订单完成。

第一阶段询问
老板 主板供应商 CPU供应商 内存供应商 是否有两个主板 主板库存有五个 有 是否有四颗CPU 主板库存有十颗 有 是否有两条1G的内存条 1G内存条 库存有二十条 有 老板 主板供应商 CPU供应商 内存供应商

此时第一阶段的询问得到结果,大家都回复了有,接下来就进入第二阶段。

第二阶段提交
老板 主板供应商 CPU供应商 内存供应商 订购两个主板 主板将库存减去两 个 发货 CPU库存减去四颗 订购四颗CPU 发货 1G内cut 库存减去两条 订购两条1G的内存条 发货 老板 主板供应商 CPU供应商 内存供应商

当发货完成之后,三家供应商的库存分别为主板供应商为3,CPU供应商为6,内存供应商为18。这两个阶段就对应为两阶段提交的第一阶段与第二阶段。

在第一阶段准备的时候:

  1. 协调者接受到客户端(本例中的用户下单)的请求;
  2. 协调者向所有的参与者(本例中的三个供应商)发送PREPARE消息,询问是否能够参与提交(本例中是否有足够的库存);
  3. 协调者此时进入等待状态,如果在等待一定时间后,没有收到所有响应OK的消息后或者参与者响应不能参与则向已经回复准备完成的参与者发送ABORT命令,中止;
  4. 只有所有的参与者响应OK的时候就进入第二阶段,参与者在回复OK之后就进入超时等待状态,如果超时还没接受到第二阶段的提交信息则证明超时。

第二阶段提交:

  1. 协调者向所有的参与者发送COMMIT消息;
  2. 协调者等待所有的参与者回复ACK,如果在等待一定时间后,没有收到所有响应ACK的消息后或者参与者响应ABORT,此时就想所有的已经执行COMMIT的参与者发送回滚消息,并中止该提交;
  3. 协调者收到所有响应的ACK后,完成本次提交。

这两个阶段的主要逻辑流程如上所示,接下来分析一下,出现异常的情况。

两阶段提交故障分析
在第一阶段故障分析
老板 主板供应商 CPU供应商 内存供应商 是否有两个主板 主板库存有一个 没有 是否有四颗CPU 主板库存有十颗 有 放弃 老板 主板供应商 CPU供应商 内存供应商

当有任意一个参与者回复没有的时候,此时整个事务就会终止此时就会向CPU供应商回复中止的消息,或者此时内存供应商没有回复的时候,此时在等待一定时间之后就会向CPU供应商回复中止消息。这种情况属于在准备阶段就出现不能进行的操作,此时就会都退出操作。

在第二阶段故障分析
老板 主板供应商 CPU供应商 内存供应商 订购两个主板 主板将库存减去两 个 发货 CPU库存减去四颗 订购四颗CPU 不能发货或者超时没有回应 1G内cut 库存减去两条 订购两条1G的内存条 发货 老板 主板供应商 CPU供应商 内存供应商

此时如果CPU供应商在提交阶段的时候,回复不能发货,或者此时因为网络原因导致CPU供应商没有回应,此时就会协调者就会发送回滚的消息到已经提交的参与者。

老板 主板供应商 CPU供应商 内存供应商 回滚 OK 回滚 OK 老板 主板供应商 CPU供应商 内存供应商

此时的协调者就会发送回滚的消息发送已经提交事务的参与者,这样保证数据一致性。

重启或者网络中断分析

协调者宕机的情况:

  1. 如果在第一阶段协调者宕机,无论参与者是什么状态都会在等待超时,或者回复不能参与提交之后恢复到正常状态。
  2. 如果在第一阶段结束后,协调者宕机如果立刻重启,此时需要数据的恢复工作,才能继续往下执行,一般的解决方案就是通过写日志,记录当前的提交进度。
  3. 如果在第二阶段中,如果在发送COMMIT的消息的过程中,发送了一部分之后,协调者宕机,此时接收到提交消息的参与者数据提交,但是没有接收到提交信息的参与者就没有提交数据,此时会导致数据不一致。此时也可通过添加执行日志,记录执行到哪一步的状态,然后再重新启动的时候,通过日志回放,来进行恢复,去做检查各个协调者的执行情况。
  4. 如果协调者宕机,一般情况下,整个系统就不可用,这就造成了单点问题。

参与者宕机的情况:

  1. 如果在第一阶段参与者宕机或者网络不通,则会收集不到参与者的OK消息,从而中止提交。
  2. 在第二阶段协调者给参与者发送COMMIT时,参与者宕机或者网络不通,此时就协调者就会超时,从而发送给其他参与者回滚的消息,如果此时其他参与者接受不到该消息,则会出现数据不一致情况。

在此,还有部分其他情况的宕机情况,由于本人水平有限,也考虑不全。

总结

二阶段提交是一个原理相对简单,但是性能较低、存在单点的一个分布式提交协议。在整个执行流程中都是一个阻塞模型,并且一旦协调者出现问题,则整个提交流程都将不能正确执行。在二阶段协议里,也会添加一些辅助例如日志与超时,来优化该协议。由于本人才疏学浅,如有错误请批评指正。

你可能感兴趣的:(分布式相关)