分布式事务-03-三阶段提交

针对两阶段提交存在的问题,三阶段提交协议通过引入一个 预询盘 阶段,以及超时策略来减少整个集群的阻塞时间,提升系统性能?

为啥加一个流程就能减少阻塞时间,接着往下看

针对2PC存在的问题 3PC 做了如下改变

  1. 引入超时机制。同时在 TM 和 RM 中都引入超时机制。
  2. 在第一阶段和第二阶段中插入一个准备阶段。保证了在最后提交阶段之前各参与节点的状态是一致的。

超时机制:

  • 对于 TM 来说如果在指定时间内没有收到所有 RM 的应答,则可以自动退出 WAIT 状态,并向所有参与者发送 rollback 通知。

  • 对于 RM 来说如果位于 READY 状态,但是在指定时间内没有收到TM的第二阶段通知,则不能武断地执行 rollback 操作,因为TM 可能发送的是 commit 通知,这个时候执行 rollback 就会导致数据不一致。

互询机制,让 RM A 去询问其他 RM B 的执行情况。

  • 如果 B 执行了 rollback 或 commit 操作,则 A 可以大胆的与 B 执行相同的操作;
  • 如果 B 此时还没有到达 READY 状态,则可以推断出 TM 发出的肯定是 rollback 通知;
  • 如果 B 同样位于 READY 状态,则 A 可以继续询问另外的参与者。
  • 只有当所有的 RM 都位于 READY 状态时,此时两阶段提交协议无法处理,将陷入长时间的阻塞状态(TM 可能崩溃了)

3PC把2PC的准备阶段再次一分为二预询盘(can_commit)预提交(pre_commit)以及事务提交(do_commit)

流程

第一阶段 预询盘

img
  • TM 向各 RM 发送 CanCommit 的请求,询问是否可以执行事务提交操作,并开始等待各 RM 的响应
  • RM 收到 CanCommit 请求后,正常情况下,如果自身认为可以顺利执行事务,那么会反馈 Yes 响应,并进入预备状态,否则反馈 No

异常情况:

  • 部分 RM 收到 canCommit 指令后,直接反馈不能开始事务,TM 向所有参与者发送 abort 请求。
  • TM 等待反馈超时,向所有 RM 发送 abort 请求。
  • RM 预检没问题,但一直无法接收到下一步的的指令(反馈 can commit 超时 或接收RM 的下一步指令超时),自省中断事务的中断
  • RM 收到来自 TM 的 abort 请求之后执行事务中断

第二阶段 预提交

这个阶段类似2PC 的第一阶段,这个环节根据阶段 1 的参与者的反馈不同,而执行不同的逻辑:

1)如果任意一个 RM 在阶段 1 向 TM 反馈了 No 响应,或者 TM 等待 RM 反馈超时,那么就会中断事务,中断执行逻辑如下:

  1. TM 向所有 RM 发送 abort 请求
  2. RM 无论是收到来自 TM 的 abort 请求,还是等待超时,都执行事务中断

2)另一种情况,如果 TM 接收到各RM 反馈都是 Yes,那么才执行事务预提交,执行逻辑如下:

  1. TM 向各RM 发送 preCommit 请求,并进入 prepared 阶段
  2. 各 RM 接收到 preCommit 请求后执行事务操作,并将 Undo 和 Redo 信息记录到事务日记中,但事务不提交
  3. 如果各 RM 都成功执行了事务操作,那么反馈给TM Ack 响应,同时等待最终指令,提交 commit 或者终止 abort

第三阶段 事务提交

这个阶段类似 2PC 的第二个阶段,这个环节根据阶段2 RM 不同反馈,而执行不同的逻辑:

1)假设 TM 正常工作,并且有任意一个 RM 在阶段 2 反馈 No,或者在等待RM 的反馈超时后,都会主动中断事务

  • TM 向所有RM 节点发送 abort 请求
  • RM 接收到 abort 请求后,利用 undo 日志执行事务回滚,并在完成事务回滚后释放占用的资源后,向 TM 发送 ack 信息,反馈事务回滚结果
  • TM 接收到所有 RM 反馈的 ACK 消息之后,完成事务的中断

2)假设 TM 正常工作,接收到了所有 RM 的 ack 响应,那么它将从预提交阶段进入提交状态

  • TM 向所有 RM 发送 doCommit 请求
  • RM 收到 doCommit 请求后,正式提交事务,并在完成事务提交后释放占用的资源,向 TM 发送 ACK 信息,反馈事务提交结果
  • TM 接收到所有参与者 ack 信息,整个事务完成

异常情况:

  • RM 收到 PreCommit 指令并正常执行事务,给 TM 反馈 preCommit 完成后,如果未能等到下一步的 doCommit 指令超时了,会自主提交事务。因为询问阶段是一致通过的,执行到这个阶段整个事务成功的概率已经很高了
  • 部分 RM 执行 preCommit 异常,部分参与者执行 preCommit 正常,但此时 TM 挂了,那么通过 RM 的超时自醒机制,就出现部分参与者提交,部分参与者回滚,出现数据不一致。
  • TM 发送了 abort 指令,RM 超时未收到指令就提交了事务,其他 RM 收到了协调者发送的 abort 指令后执行了回滚,也会出现数据不一致。

Keidar 和 Dolev (1998) 建议使用增强型三阶段提交 (E3PC) 协议来消除此问题。E3PC 协议需要至少三个往返才能完成,这将有很长的延迟才能完成每笔交易。

总结

  1. 相较于2PC,3PC引入超时机制与质询机制,增加了额外的通信开销,增加了系统网络负载与延迟
  2. 异常情况仍然无法避免数据不一致的情况
  3. 依赖于时间同步,3PC的正确执行依赖于系统中所有 RM 和 TM 的时间同步。如果时间同步不准确,可能导致超时机制失效或误判,影响事务的最终一致性。

参考文档

  1. https://pdai.tech/md/arch/arch-z-transection.html#分布式事务方案之刚性事务