XA/2PC
XA和2PC间的关系
XA的事务模型只说明需要做什么事情, 但具体怎么实习未说明, 相对较需
2PC是将XA规范进行落地, 可以简单理解为 XA 是接口, 而 2PC 是 XA 的具体实现类(不正确的想法)
XA/2PC的角色
X/Open的组织定义了分布式事务的模型,这里面有几个角色,就是AP(Application,应用程序),TM(Transaction Manager,事务管理器),RM(Resource Manager,资源管理器),CRM(Communication Resource Manager,通信资源管理器)
XA/2PC的流程
AP让TM生成一个全局事务
阶段一prepare
准备阶段: TM向让各个RM开启一个事务, 并执行对应的sql, 但是不commit(等待TM的通知)
阶段二commit
提交阶段: 各个RM都向TM返回一个执行结果
- 如果都成功, 那么TM就让RM的事务都提交
- 如果有一个失败, 或者有一个迟迟没有响应, TM就让RM回滚各自的本地事务
只有都提交成功了, 分布式事务才叫成功
XA/2PC的问题
同步阻塞
阶段一(prepare)的时候, 数据库的资源会被占用, 直到阶段二完成, 此时有其他应用需要访问资源, 就需要等待
脑裂
如果由于网络问题, 导致后来, 一些库commit了, 另一些库没有收到commit的消息, 数据一致性出现问题
单点故障
TM是单机, 如果TM故障, 整个分布式事务就凉凉, 可能会一直卡住, 无法执行, 或者数据错误
- TM宕机, RM正常
TM宕机, 则无法下达后续指令, 在阶段一的RM会一直阻塞住 - TM、RM 都宕机
就算由主从/热备等机制, 保证TM知道对哪些机子已经发送过哪些指令, 但还是有一种问题无法解决
TM发送消息, 要所有RM执行阶段二, 假设有 2个RM, RM1接收到Commit指令并执行成功, RM2接到Commit指令但是没执行就宕机了, 虽然可以通过其他通信手段使得最终事务一致, 但是在该通信手段执行期间, AB是不一致的, 整个数据是有问题的
(其实RM2到底执行了没有是不知道的, 因为宕机了不知道是否执行提交了没)
3PC
三阶段提交就有CanCommit、PreCommit、DoCommit三个阶段。
3PC流程
CanCommit 阶段
TM发送消息给各个RM, RM返回一个响应, 说明TM与各个RM之间网络通信正常(感觉有点像http协议)
PreCommit 阶段
像 2PC 的阶段一, 没什么不同的
DoCommit 阶段
像 2PC 的阶段二, 就多一个RM没有无法及时接收到来自TM的doCommit或者abort请求时,会在等待超时之后直接提交事务
3PC相对2PC的变动点
TM的超时响应机制
当TM宕机后, RM在长时间未接收到TM的指令时, 会自动提交本地事务(但还是无法解决事务一致性问题)
将2PC的阶段一拆分为2个阶段(CanCommit、PreCommit)
就是看看会不会有网络问题, 如脑裂之类的问题
优点
降低同步阻塞
事务开启后会先判断基本环境是否畅通, 而不是直接执行事务, 一定程度上避免了某个RM出现问题, 而其他RM已经执行了SQL还需要回滚(对资源的占用)
RM超时会自动提交, 避免RM一直占用资源
一定程度上提高了数据的一致性
可以解决, 当TM宕机, 部分RM提交, 而有的RM为收到 doCommit 命令, 那么这些RM超时会自动提交
可以这么理解, 当在doCommit阶段的时候, 说明canCommit阶段全部通过, 那么事务会很大概率能执行成功(为什么这么乐观?), 所以当canCommit的时候一直没有接到commit或abort指令, 很可能是TM宕机了, 那直接自行commit
缺点
产生新的数据不一致问题
如果TM是要求回滚, RM应该收到abort命令回滚, 然后还没全发完TM就宕机, 那么会导致部分RM回滚, 而超时的RM会自动提交
JTA
j2ee里面的一XA标准提出的一套API
缺点是实现复杂, 比较笨重, 现在用的人不多了