一.事务的定义
事务提供一种机制将一个活动涉及的所有操作纳入到一个不可分割的执行单元,组成事务的所有操作只有在所有操作均能正常执行的情况下方能提交
只要其中任一操作执行失败,都将导致整个事务的回滚
简单地说,事务提供一种“要么什么都不做,要么都做(All or Nothing)”机制。
二.事务的ACID特性
1.原子性(A)
所谓的原子性就是说,在整个事务中的所有操作,要么全部完成,要么全部不做,没有中间状态。对于事务在执行中发生错误,所有的操作都会被回滚,整个事务就像从没被执行过一样。
2.一致性(C)
事务的执行必须保证系统的一致性,就拿转账为例,A有500元,B有300元,如果在一个事务里A成功转给B50元,那么不管并发多少,不管发生什么,只要事务执行成功了,那么最后A账户一定是450元,B账户一定是350元。
3.隔离性(I)
所谓的隔离性就是说,事务与事务之间不会互相影响,一个事务的中间状态不会被其他事务感知。
4.持久性(D)
所谓的持久性,就是说一单事务完成了,那么事务对数据所做的变更就完全保存在了数据库中,即使发生停电,系统宕机也是如此。
三.什么是分布式事务?
分布式事务就是指事务的参与者、支持事务的服务器、资源服务器以及事务管理器分别位于不同的分布式系统的不同节点之上。
简单的说,就是一次大的操作由不同的小操作组成,这些小的操作分布在不同的服务器上,且属于不同的应用,分布式事务需要保证这些小操作要么全部成功,要么全部失败。
本质上来说,分布式事务就是为了保证不同数据库的数据一致性。
![](https://i-blog.csdnimg.cn/blog_migrate/4a7588410b3d43945347584a70096711.png)
四.分布式事务产生的原因
service多个节点:
![](https://i-blog.csdnimg.cn/blog_migrate/f41c0295c7ef4ac629165ab5fad86aaf.png)
resource多个节点:
![](https://i-blog.csdnimg.cn/blog_migrate/2a2f9fd31d00c3abcc30c5fc253a3bfd.png)
五.分布式事务的理论基础
1.CAP定理
C (一致性):对某个指定的客户端来说,读操作能返回最新的写操作。
A (可用性):非故障的节点在合理的时间内返回合理的响应(不是错误和超时的响应)。
P (分区容错性):当出现网络分区后,系统能够继续工作。
![](https://i-blog.csdnimg.cn/blog_migrate/8a7872844ca31e5d6d4f3b56eeafd6c1.png)
2.BASE定理
基本可用(Basically Available):分布式系统在出现故障时,允许损失部分可用功能,保证核心功能可用。
软状态(Soft state):允许系统中存在中间状态,这个状态不影响系统可用性,这里指的是CAP中的不一致。
最终一致(Eventually consistent):最终一致是指经过一段时间后,所有节点数据都将会达到一致。
六.分布式事务解决方案
1.2PC(两阶段提交)
两阶段提交问题
性能问题:所有参与者在事务提交阶段处于同步阻塞状态,占用系统资源,容易导致性能瓶颈。
可靠性问题:如果协调者存在单点故障问题,或出现故障,提供者将一直处于锁定状态。
数据一致性问题:在阶段 2 中,如果出现协调者和参与者都挂了的情况,有可能导致数据不一致。
优点:尽量保证了数据的强一致,适合对数据强一致要求很高的关键领域
缺点:实现复杂,牺牲了可用性,对性能影响较大,不适合高并发高性能场景。
![](https://i-blog.csdnimg.cn/blog_migrate/e07380f67ae484b38a2f06dd23c29172.png)
2.3PC(三阶段提交)
三阶段提交问题
1. 和2PC比较:
3PC对于协调者(Coordinator)和参与者(Partcipant)都设置了超时时间,而2PC只有协调者才拥有超时机制
2. 优点:相比二阶段提交,三阶段提交降低了阻塞范围,在等待超时后协调者或参与者会中断事务。避免了协调者单点问题。阶段 3 中协调者出现问题时,参与者会继续提交事务。
3. 缺点:数据不一致问题依然存在,当在参与者收到 preCommit 请求后等待 do commite 指令时,此时如果协调者请求中断事务,而协调者无法与参与者正常通信,会导致参与者继续提交事务,造成数据不一致。
![](https://i-blog.csdnimg.cn/blog_migrate/f2babc843c463f93a7fcc17618bcc9de.png)
4.TCC(补偿事务)
TCC方案分为Try Confirm Cancel三个阶段
Try:尝试待执行的业务
这个过程并未执行业务,只是完成所有业务的一致性检查,并预留好执行所需的全部资源
Confirm:执行业务
这个过程真正开始执行业务,由于Try阶段已经完成了一致性检查,因此本过程直接执行,而不做任何检查。并且在执行的过程中,会使用到Try阶段预留的业务资源。
Cancel:取消执行的业务
若业务执行失败,则进入Cancel阶段,它会释放所有占用的业务资源,并回滚Confirm阶段执行的操作
TCC问题
优点:
性能提升:具体业务来实现控制资源锁的粒度变小,不会锁定整个资源。
数据最终一致性:基于 Confirm 和 Cancel 的幂等性,保证事务最终完成确认或者取消,保证数据的一致性。
可靠性:解决了 XA 协议的协调者单点故障问题,由主业务方发起并控制整个业务活动,业务活动管理器也变成多点,引入集群。
缺点:
对应用的侵入性强。业务逻辑的每个分支都需要实现try、confirm、cancel三个操作,应用侵入性较强,改造成本高。
实现难度较大。需要按照网络状态、系统故障等不同的失败原因实现不同的回滚策略。为了满足一致性的要求,confirm和cancel接口必须实现幂等。
5.本地消息表
支付宝系统 : message表 :1.messageId 2.状态 comfirm uncomfirm 3.留回调接口改变状态
支付宝系统 : 有线程扫描 uncomfirm 的消息 再放到消息中间件 。 余额宝系统操作成功 ,如果成功 回调 更改支付宝为comfirm
余额宝系统: message表:1.messageId=支付宝messageId (消费消息前查看messageId是否存在如果已经存在代表已经消费过了 就不需要消费)解决重复消费问题
优点:从应用设计开发的角度实现了消息数据的可靠性,消息数据的可靠性不依赖于消息中间件,弱化了对 MQ 中间件特性的依赖。
缺点:与具体的业务场景绑定,耦合性强,不可公用。消息数据与业务数据同库,占用业务系统资源。业务系统在使用关系型数据库的情况下,消息服务性能会受到关系型数据库并发性能的局限。
6.消息事务最终一致性方案(基于支持事务的MQ)
该方案基于本地消息表进行优化,不使用本地消息表,而是基于MQ,比如阿里的RocketMQ就支持消息事务
事务发起方首先发送prepare消息到MQ。
在发送prepare消息成功后执行本地事务。
根据本地事务执行结果返回commit或者是rollback。
如果消息是rollback,MQ将删除该prepare消息不进行下发,如果是commit消息,MQ将会把这个消息发送给consumer端。
如果执行本地事务过程中,执行端挂掉,或者超时,MQ将会不停的询问其同组的其它producer来获取状态。
Consumer端的消费成功机制有MQ保证。
![](https://i-blog.csdnimg.cn/blog_migrate/bd3a6842c86c6a8b1114a77ecf1b316a.png)
条件:
a) 需要补偿逻辑
b) 业务处理逻辑需要幂等
优点:
消息数据独立存储,降低业务系统与消息系统之间的耦合。
吞吐量优于本地消息表方案。
缺点:
一次消息发送需要两次网络请求(half消息 + commit/rollback)。
需要实现消息回查接口。
7.Saga事务
Saga 事务核心思想是将长事务拆分为多个本地短事务并依次正常提交,如果所有短事务均执行成功,那么分布式事务提交;如果出现某个参与者执行本地事务失败,则由 Saga 事务协调器协调根据相反顺序调用补偿操作,回滚已提交的参与者,使分布式事务回到最初始的状态。Saga 事务基本协议如下:
(1)每个 Saga 事务由一系列幂等的有序子事务(sub-transaction) Ti 组成。
(2)每个 Ti 都有对应的幂等补偿动作 Ci,补偿动作用于撤销 Ti 造成的结果。
与TCC事务补偿机制相比,TCC有一个预留(Try)动作,相当于先报存一个草稿,然后才提交;Saga事务没有预留动作,直接提交。
优点:
服务之间关系简单,避免服务间循环依赖,因为 Saga 协调器会调用 Saga 参与者,但参与者不会调用协调器。
程序开发简单,只需要执行命令/回复(其实回复消息也是一种事件消息),降低参与者的复杂性。
易维护扩展,在添加新步骤时,事务复杂性保持线性,回滚更容易管理,更容易实施和测试。
缺点:
中央协调器处理逻辑容易变得庞大复杂,导致难以维护。
存在协调器单点故障风险
![](https://i-blog.csdnimg.cn/blog_migrate/6edb5b3a1a339ce7d7144f4ec6d9e45d.png)
总结
能不用分布式事务就不用
如果非得使用的话,结合自己的业务分析,看看自己的业务比较适合哪一种,是在乎强一致,还是最终一致即可。