SpringCloud-高级篇(七)

前面在微服务里整合了Seata,下面利用Seata去解决分布式事务的问题,回去学习Seata中的四种解决方案  :首先学习XA模式

SpringCloud-高级篇(七)_第1张图片

(1)XA模式

SpringCloud-高级篇(七)_第2张图片

RM在前面讲的是资源管理器,在XA标准中RM都是由数据库来实现的,数据库本身实现了这个功能

XA是分布时事务领域最早的一个标准,几乎主流的数据库都实现了这个标准

SpringCloud-高级篇(七)_第3张图片

XA是基于数据库本身的特性来去实现分布式事物的,是能够满足ACID的特性的,它是一种强一致性的事务

SpringCloud-高级篇(七)_第4张图片

SpringCloud-高级篇(七)_第5张图片

Seata实现的 是在数据库xa模式基础上做了一层封装,实现起来是比较简单的  ,它多了一个TM做整个事务的一个注册个管理,变的健壮

优势:

1.在第一阶段只是执行事务而不提交,事务一直处于运行中的一个状态的,事务本身具备ACID的特性,到了第二阶段,等到所有的分支事务都执行完了然后才一起提交,因为这个特性,每个事务都是ACID的,并且大家相互等待,因此整个事务都能实现ACID,认为这种XA具备强一致性的

2.数据库本身都实现了XA模式,数据库本身已经实现了对应的接口,你调用我我去执行,实现各种各样的功能,它是比较容器去实现分布式的效果的,Seata实现这种XA模式的时候也仅仅是在数据库接口上做了一层简单的封装形成RM,用起来非常的简单 

 缺点:

1.第一阶段不提交,等着第二阶段在提交,在等的时候占用数据库的锁,比如一个事务跨越了四五个更多的事务,每个事务执行完了还得等着别人,如果这个业务耗时较长,四五个分支都执行完耗时很久,整个事务过程中不提交占用系统资源,占用数据库锁,被人都不能访问,是一种资源的浪费,性能比较差,可用性低

2.这种方式依赖数据库底层的实现的,用起来比较简单了,但是如果数据库不支持比如Redis库,就没有办法做了

SpringCloud-高级篇(七)_第6张图片

把数据源形成了一个代理,将来发起的业务sql,都会被Seata(RM)拦截下来,内部调用数据的这种接口,从而实现XA模式,数据源的配置,在参与全局事务的微服务里都需要去添加

给去全局事务的入口方法添加全局事务的注解,全局事务都由一个入口,这个入口要把它标记起来,这样我们的Seata就知道去全局事务是从哪里开始的,就会用TM代理这个方法,从这个方法开始,调用了哪些微服务我们的Seata就知道了,一个微服务的参与者就是一个分支事务了这样去全局事务的边界就定义下来了 ,这个注解只要在入口添加

SpringCloud-高级篇(七)_第7张图片

(2)XA模式实现

在每个微服务里添加:XA配置 

SpringCloud-高级篇(七)_第8张图片

SpringCloud-高级篇(七)_第9张图片

SpringCloud-高级篇(七)_第10张图片

在OrderService中的入口方法添加注解:@GlobalTransation

SpringCloud-高级篇(七)_第11张图片

重启微服务

在Seata控制台里服务会重新注册:

现在的数据库:

Order表 

SpringCloud-高级篇(七)_第12张图片

 account表

SpringCloud-高级篇(七)_第13张图片

storage表: 

SpringCloud-高级篇(七)_第14张图片

发起订单当余额充足,数量充足的时候:

SpringCloud-高级篇(七)_第15张图片

数据库表正常减少:

库存-2

SpringCloud-高级篇(七)_第16张图片

越-2 

SpringCloud-高级篇(七)_第17张图片

订单新增:

SpringCloud-高级篇(七)_第18张图片

当购买数量超过剩余的:SpringCloud-高级篇(七)_第19张图片

去看数据库会不会回滚:发现数据库还是原样没有发生变化,发生了回滚

SpringCloud-高级篇(七)_第20张图片

SpringCloud-高级篇(七)_第21张图片

SpringCloud-高级篇(七)_第22张图片

查看日志:库存报错了

SpringCloud-高级篇(七)_第23张图片

余额执行了回滚 

SpringCloud-高级篇(七)_第24张图片

(3)AT模式

AT模式跟XA模式的区别是执行完业务sql,而是直接提交不是等待执行,就没有资源的等待了,直接释放了,性能就会提高 

SpringCloud-高级篇(七)_第25张图片

虽然提交了,但是怎么保持数据状态的一致性呢?它会在提交前后形成一个快照,如果有问题及时回滚原样

SpringCloud-高级篇(七)_第26张图片

SpringCloud-高级篇(七)_第27张图片

SpringCloud-高级篇(七)_第28张图片

SpringCloud-高级篇(七)_第29张图片

(4)AT模式存在的问题

AT相比XA模式性能得到了提高,但是正是由于提前释放了资源,没有去做锁,这就导致了在并发访问的时候,会存在一些安全问题

SpringCloud-高级篇(七)_第30张图片

SpringCloud-高级篇(七)_第31张图片

会存在并发访问是,丢失更新的问题,事务一回滚后的是100,相当于事务二没有进行操作

这是因为事务没有存在隔离,事务2插入进来,事务一阶段二运行的时候出现脏数据,归根是隔离的原因,比如说阶段一和阶段二都是一个锁定状态,别人没有办法插入进来,就不会出现问题

为了解决这个问题AT模式引入全局锁

SpringCloud-高级篇(七)_第32张图片

虽然说加了全局锁,但是AT模式的性能依赖比XA模式好,XA是数据库的锁,锁不释放,所有人不能访问数据,因为全局锁记录操作这张表的全局事务有Seata来管理的,如果其他事务(比如修改的是其他字段)不是有Seata来管理的 是没有影响的,AT全局锁锁定的范围是比较小的,所以性能较好

但是可能会有极端的情况 当你在修改money的过程中,有一个其他的事务没有由Seata来管理,这个时候他不需要获取全局锁也会出现这种问题,只是这种可能较低

原因:1.因为全局事务大多数执行是成功的  2.分布式事务耗时比较长,因此它的并发比较低,我们在业务上也会尽量避免多个事务去操作了同一个字段

AT对于这种极少的情况也可以这样解决:

事务一会拿更新后的快照,跟当前的数据库的值作一个对比,如果一样则证明没有其他事务更改过,可以进行回滚,不一样说明有事务做了更改Seata就知道不能修改了,这个时候需要人工介入解决

SpringCloud-高级篇(七)_第33张图片

SpringCloud-高级篇(七)_第34张图片

(5)AT模式实现

SpringCloud-高级篇(七)_第35张图片

全局锁表lock_table 快照表undo_log

在seata相关的库中中导入

SpringCloud-高级篇(七)_第36张图片

SpringCloud-高级篇(七)_第37张图片

SpringCloud-高级篇(七)_第38张图片

在于微服务相关的库seata_demo中新建:

SpringCloud-高级篇(七)_第39张图片

更改每个微服务的模式:ATSpringCloud-高级篇(七)_第40张图片

SpringCloud-高级篇(七)_第41张图片

SpringCloud-高级篇(七)_第42张图片

重启服务:查看数据库表

SpringCloud-高级篇(七)_第43张图片

SpringCloud-高级篇(七)_第44张图片

SpringCloud-高级篇(七)_第45张图片

发起异常订单: 

SpringCloud-高级篇(七)_第46张图片

然后查询数据库还是原样

SpringCloud-高级篇(七)_第47张图片

 新建的表也是临时存储一下数据,事务回滚完也就删除了,打断点可以看到表中的数据

SpringCloud-高级篇(七)_第48张图片

你可能感兴趣的:(spring,cloud,spring,后端)