关于java:分布式事务三之三阶段提交

2次阅读

共计 2042 个字符,预计需要花费 6 分钟才能阅读完成。

三阶段提交(3PC)是二阶段提交(2PC)的改良版本,三阶段提交协定次要是为了解决两阶段提交协定的阻塞问题,2pc 存在的问题是当协调者解体时,参与者不能做出最初的抉择。因而参与者可能在协调者复原之前放弃阻塞。三阶段提交(Three-phase commit),是二阶段提交(2PC)的改良版本。

三阶段提交 3PC

与两阶段提交不同的是,三阶段提交有两个改变点:

  • 引入超时机制。同时在协调者和参与者中都引入超时机制;
  • 在第一阶段和第二阶段中插入一个筹备阶段。保障了在最初提交阶段之前各参加节点的状态是统一的。

3PC 把 2PC 的筹备阶段再次一分为二,这样三阶段提交就有 CanCommit、PreCommit、DoCommit 三个阶段。

CanCommit 阶段

之前 2PC 的一阶段是本地事务执行完结后,最初不 Commit,等其它服务都执行完结并返回 Yes,由协调者产生 commit 才真正执行 commit。而这里的 CanCommit 指的是 尝试获取数据库锁 如果能够,就返回 Yes。这阶段次要分为 2 步

  • 事务询问:协调者向参与者发送 CanCommit 申请。询问是否能够执行事务提交操作。而后开始期待参与者的响应;
  • 响应反馈:参与者接到 CanCommit 申请之后,失常状况下,如果其本身认为能够顺利执行事务,则返回 Yes 响应,并进入准备状态。否则反馈 No。

PreCommit 阶段

在阶段一中,如果所有的参与者都返回 Yes 的话,那么就会进入 PreCommit 阶段进行事务预提交。这里的 PreCommit 阶段 跟下面的第一阶段是差不多的,只不过这里协调者和参与者都引入了超时机制(2PC 中只有协调者能够超时,参与者没有超时机制),次要蕴含两个步骤:

  • 事务预提交:参与者接管到 PreCommit 申请后,会执行事务操作,并将 undo 和 redo 信息记录到事务日志中。
  • 响应反馈:如果参与者胜利的执行了事务操作,则返回 ACK 响应,同时开始期待最终指令。

如果有任何一个参与者向协调者发送了 No 响应,或者期待超时之后,协调者都没有接到参与者的响应,那么就执行事务的中断:

  • 发送中断请求:协调者向所有参与者发送 abort 申请。
  • 中断事务:参与者收到来自协调者的 abort 申请之后(或超时之后,仍未收到协调者的申请),执行事务的中断。

DoCommit 阶段

该阶段进行真正的事务提交,也能够分为以下两种状况。

执行提交 ,发送提交申请 协调接管到参与者发送的 ACK 响应,那么他将从预提交状态进入到提交状态。并向所有参与者发送 doCommit 申请。

  • 事务提交:参与者接管到 doCommit 申请之后,执行正式的事务提交。并在实现事务提交之后开释所有事务资源。
  • 响应反馈:事务提交完之后,向协调者发送 Ack 响应。
  • 实现事务:协调者接管到所有参与者的 ack 响应之后,实现事务。

中断事务 ,协调者没有接管到参与者发送的 ACK 响应(可能是接受者发送的不是 ACK 响应,也可能响应超时),那么就会执行中断事务。

  • 发送中断请求:协调者向所有参与者发送 abort 申请
  • 事务回滚:参与者接管到 abort 申请之后,利用其在阶段二记录的 undo 信息来执行事务的回滚操作,并在实现回滚之后开释所有的事务资源。
  • 反馈后果:参与者实现事务回滚之后,向协调者发送 ACK 音讯
  • 中断事务:协调者接管到参与者反馈的 ACK 音讯之后,执行事务的中断。

总结

绝对于 2PC,3PC 次要解决的单点故障问题,并缩小阻塞,因为一旦参与者无奈及时收到来自协调者的信息之后,他会默认执行 commit。而不会始终持有事务资源并处于阻塞状态。然而这种机制也会导致数据一致性问题,因为,因为网络起因,协调者发送的 abort 响应没有及时被参与者接管到,那么参与者在期待超时之后执行了 commit 操作。这样就和其余接到 abort 命令并执行回滚的参与者之间存在数据不统一的状况。

在 2PC 中一个参与者的状态只有它本人和协调者通晓,如果协调者提议后本身宕机,在协调者备份启用前一个参与者又宕机,其余参与者就会进入既不能回滚、又不能强制 commit 的阻塞状态,直到参与者宕机复原。

参与者如果在不同阶段宕机,咱们来看看 3PC 如何应答:

  • 阶段 1: 协调者或协调者备份未收到宕机参与者的 vote,间接停止事务;宕机的参与者复原后,读取 logging 发现未收回赞成 vote,自行停止该次事务
  • 阶段 2: 协调者未收到宕机参与者的 precommit ACK,但因为之前曾经收到了宕机参与者的赞成反馈 (不然也不会进入到阶段 2),协调者进行 commit;协调者备份能够通过问询其余参与者取得这些信息,过程同理;宕机的参与者复原后发现收到 precommit 或曾经收回赞成 vote,则自行 commit 该次事务
  • 阶段 3: 即使协调者或协调者备份未收到宕机参与者 t 的 commit ACK,也完结该次事务;宕机的参与者复原后发现收到 commit 或者 precommit,也将自行 commit 该次事务。

我是御狐神,欢送大家关注我的微信公众号:wzm2zsd

本文最先公布至微信公众号,版权所有,禁止转载!

正文完
 0