分布式事务-刚性事务

Heer Liu

说到刚性事务,首先要讲的是XA协议。XA协议是一个基于数据库的分布式事务协议,其分为两部分:事务管理器(Transaction Manager)和 本地资源管理器(Resource Manager)。事务管理器作为一个全局的调度者,负责对各个本地资源管理器统一号令提交或者回滚。二阶提交协议(2PC)三阶提交协议(3PC)就是根据此协议衍生出来而来。主流的诸如Oracle、MySQL等数据库均已实现了XA接口。

XA接口是双向的系统接口,在事务管理器(Transaction Manager)以及一个或多个资源管理器(Resource Manager)之间形成通信桥梁。也就是说,在基于XA的一个事务中,我们可以针对多个资源进行事务管理,例如一个系统访问多个数据库,或即访问数据库、又访问像消息中间件这样的资源。这样我们就能够实现在多个数据库和消息中间件直接实现全部提交、或全部取消的事务。XA规范不是java的规范,而是一种通用的规范; Java 中的规范是JTA和JTS:Java事务API(Java Transaction API)是一个Java企业版的应用程序接口,在Java环境中,允许完成跨越多个XA资源的分布式事务;Java事务服务(Java Transaction Service)是J2EE平台提供了分布式事务服务的具体实现规范,j2ee服务器提供商根据JTS规范实现事务并提供JTA接口

两段提交(2PC)

引入一个作为协调者(coordinator)的组件来统一掌控所有参与者(participant)的操作结果,并最终指示这些节点是否要把操作结果进行真正的提交。

简单而言:参与者(participant)用来管理资源,协调者(coordinator)用来协调事务状态

两段提交(2PC - Prepare & Commit)是指两个阶段的提交:

  • 第一阶段

    准备阶段

    • 协调者向所有参与者发送 REQUEST-TO-PREPARE
    • 当参与者收到REQUEST-TO-PREPARE 消息后, 它向协调者发送消息PREPARED或者NO,表示事务是否准备好;如果发送的是NO,那么事务要回滚;
  • 第二阶段

    提交阶段

    • 协调者收集所有参与者的返回消息, 如果所有的参与者都回复的是PREPARED, 那么协调者向所有参与者发送COMMIT 消息;否则,协调者向所有回复PREPARED的参与者发送ABORT消息;
    • 参与者如果回复了PREPARED消息并且收到协调者发来的COMMIT消息,或者它收到ABORT消息,它将执行提交或回滚,并向协调者发送DONE消息以确认。

img

两段提交(2PC)的缺点

二阶段提交看似能够提供原子性的操作,但它存在着严重的缺陷:

  • 网络抖动导致的数据不一致:第二阶段中协调者向参与者发送commit命令之后,一旦此时发生网络抖动,导致一部分参与者接收到了commit请求并执行,可其他未接到commit请求的参与者无法执行事务提交。进而导致整个分布式系统出现了数据不一致。
  • 超时导致的同步阻塞问题:2PC中的所有的参与者节点都为事务阻塞型,当某一个参与者节点出现通信超时,其余参与者都会被动阻塞占用资源不能释放。
  • 单点故障的风险:由于严重的依赖协调者,一旦协调者发生故障,而此时参与者还都处于锁定资源的状态,无法完成事务commit操作。虽然协调者出现故障后,会重新选举一个协调者,可无法解决因前一个协调者宕机导致的参与者处于阻塞状态的问题。

2PC小结

2PC除本身的算法局限外,还有一个使用上的限制,就是它主要用在两个数据库之间(数据库实现了XA协议)。两个系统之间是无法使用2PC的,因为不会直接在底层的两个业务数据库之间做一致性,而是在两个服务上面实现一致性。

2PC只适用两个数据库(数据库实现了XA协议)之间;2PC有诸多问题和不便,在实践中一般很少使用

三段提交(3PC)

三段提交(3PC)是对两段提交(2PC)的一种升级优化,3PC在2PC的第一阶段和第二阶段中插入一个准备阶段。保证了在最后提交阶段之前,各参与者节点的状态都一致。同时在协调者和参与者中都引入超时机制,当参与者各种原因未收到协调者的commit请求后,会对本地事务进行commit,不会一直阻塞等待,解决了2PC的单点故障问题,但3PC还是没能从根本上解决数据一致性的问题。

3PC的三个阶段分别是CanCommit、PreCommit、DoCommit

  • CanCommit:协调者向所有参与者发送CanCommit命令,询问是否可以执行事务提交操作。如果全部响应YES则进入下一个阶段。
  • PreCommit:协调者向所有参与者发送PreCommit命令,询问是否可以进行事务的预提交操作,参与者接收到PreCommit请求后,如参与者成功的执行了事务操作,则返回Yes响应,进入最终commit阶段。一旦参与者中有向协调者发送了No响应,或因网络造成超时,协调者没有接到参与者的响应,协调者向所有参与者发送abort请求,参与者接受abort命令执行事务的中断。
  • DoCommit:在前两个阶段中所有参与者的响应反馈均是YES后,协调者向参与者发送DoCommit命令正式提交事务,如协调者没有接收到参与者发送的ACK响应,会向所有参与者发送abort请求命令,执行事务的中断。

img

3PC存在的问题

3PC工作在同步网络模型上,它假设消息传输时间是有上界的,只存在机器失败而不存在消息失败。这个假设太强,现实的情形是,机器失败是无法完美地检测出来的,消息传输可能因为网络拥堵花费很多时间。同时, 说阻塞是相对, 存在协调者和参与者同时失败的情形下, 3PC事务依然会阻塞。实际上,很少会有系统实现3PC,多数现实的系统会通过复制状态机解决2PC阻塞的问题。比如,如果失败模型不是失败-停止, 而是消息失败(消息延迟或网络分区),那样3PC会产生不一致的情形。

3PC并没有完美解决2PC的阻塞,也引入了新的问题(不一致问题),所以3PC很少会被真正的使用

  • 标题: 分布式事务-刚性事务
  • 作者: Heer Liu
  • 创建于: 2022-08-21 21:35:17
  • 链接: https://blog.heer.love/posts/9c9cf1a5/
  • 版权声明 : 本文章采用 CC BY-NC-SA 4.0 进行许可。
推荐阅读
分布式事务-柔性事务 分布式事务-柔性事务 分布式锁-基于数据库 分布式锁-基于数据库 分布式系统 分布式系统
此页目录
分布式事务-刚性事务