一、为什么需要分布式事务:
分布式事务是指 会涉及到操作多个数据库(服务)的事务。
其实就是将对 同一数据库(服务)事务的概念扩大到了多个数据库(服务)的事务。
目的是为了保证分布式系统中的数据一致性。
二、分布式事务XA规范:
什么是XA规范:
XA规范是一种用于实现分布式事务的标准,它定义了一组接口和协议,用于协调分布式环境下多个资源管理器(Resource Manager)之间的事务操作。
XA规范的全称是"X/Open Distributed Transaction Processing (DTP) XA",最初由X/Open(现在的The Open Group)制定并发布。它提供了两个关键接口:XA接口和RM接口。
其中XA里面有这几个角色:
- AP(Application,应用程序)
- TM(Transaction Manager,事务管理器)
- RM(Resource Manager,资源管理器)
XA规范:就是X/Open DTP定义的 事务协调者 与数据库之间的接口规范,(既接口函数),事务协调者 用它来通知数据库事务的开始、结束以及提交、回滚等操作。
XA规范的实现:分布式集群的情况下,一般加代理层来充当TM的角色,实现对事务的支持。
其中二阶段提交协议(2PC)和三阶段提交协议(3PC)就是根据XA规范这一思想衍生出来的。
两阶段提交主要保证了分布式事务的原子性:既所有节点要么全成功,要么全不成功。
三、二阶段提交(2PC):
3.1 第一阶段:
- 事务协调者(TM)给各个节点发送 执行 指令,然后两个服务开始执行,如果两个服务的业务逻辑都没有问题反馈给事务协调者。这时两个服务的数据还没有提交至数据库。为什么呢?(往下看)
- 假如现在事务协调者收到这两个都没有问题。然后事务协调者发送提交指令,两个进行提交。
3.2 第二阶段:
3. 这个时候两个服务都提交了。(完成事务)
4. 然后我们重新来演示下 第一阶段提交问题。
5. 看上图,在库存节点的时候内部报错了,响应给协调者,或者说库存节点迟迟不给协调者回应,超出了一定的时间,那么第2阶段就变成回滚报错了。(完成事务)
3.3 二阶段提交的缺点和解决办法:
- 事务协调者故障(各个节点的协调会失败)
给事务协调者增加集群
- 占用数据库连接 (数据库链接阻塞,就是我们的第1步骤,需要等待协调者响应才能提交到数据库)
这个也是可以解决的,就是如果第1阶段都没有问题,那么就直接提交,然后记录数据原来的状态。如果第2阶段如果事务协调者让回滚的话。我们可以根据数据原来的状态直接进行回滚操作,这样就解决了占用链接的问题了。(阿里云的Seata就是这么干的)
- 网络波动,数据不一致:为什么会产生这个问题呢?
如果我们的第一阶段都没有问题的话,在第二阶段的时候,
这种方式的情况下,只能人工手动解决。。
四、三阶段提交(3PC):
3pc阶段提交示例图:
其实3pc提交的后两个阶段 pre commit和 do commit 就是2pc提交的方式。那为什么要有3pc提交呢?
3pc的出现其实就为了解决 2pc 的第一步长久占用数据库连接。还有2pc的第二阶段,如果某个节点迟迟不给回应。
4.1. 3pc的第一阶段:
如果3pc的第一个can commit,A节点和B节点收到TM的指令后,然后检查自己的程序,检查自己的sql,如果没问题。响应给TM,如果有一个节点检查返回的错误的信息。或者一个节点迟迟不给回应。那么这一阶段 就直接结束了。
4.2. 3pc的第二阶段:
假如第一阶段,节点都返回ok。那么来到第二阶段
如果第二节点还是有一个节点,返回no,或者迟迟不回应,那么就直接回滚操作。
4.2. 3pc的第三阶段:
如果第三阶段。两个节点都是yes,那么咱们整个流程就走完了。如果在第三阶段有一个阶段迟迟没有给TM响应。那咱们的失联节点服务里面。就应该有判断自动提交的逻辑。为什么?(因为我们前两个阶段都是没有问题的。这样不就解决了2阶段的问题了么?)
五、TCC(Try Confirm Cancel)的方式:
其实tcc的方式,就是在操作最终一致性上面去添加日志信息。比如我们现在有个业务场景
张三给李四转账100,李四增加100,张三减100
相对于2PC、3PC、Tcc使用的范围量大,我们不止可以恢复mysql,更可以恢复redis等等。但是开发量大,业务代码量也大,我们每次执行必要的操作。都需要写相应恢复操作的代码。
阿里云的Seata就支持TCC这种模式。