分布式事务Seata<XA模式、AT模式>解决方案思路(针对多数据源、分库分表、微服务、微服务分库分表4种场景)

发布于:2024-04-29 ⋅ 阅读:(24) ⋅ 点赞:(0)

seata的xa的方式解决 保证强一致性
原理说明:
1.启动seata服务器TC(控制台7091可以查看)
2.启动spring项目 初始化TM RM,实际上TM和RM注册到TC中
3.浏览器访问执行方法,TM向TC请求开启全局事务,
返回一个全局事务id,存储在threadlocal中;
4.资源管理器threadlocal中获取id,向tc注册分支事务必须携带全局事务,
TC会将分支事务会加入到全局事务中,返回RM一个分支事务id
5注册分支事务成功后,向TC报告执行情况
6.另一个RM同理执行4和5
7.如果都执行成功,TM会通知TC做提交,TC会通知RM做提交
8.如果执行失败,TM会通知TC做回滚,TC会通知RM做回滚

!!!跨数据库
单体项目 配置多数据源
    1.运行2个MySQL
    2.自动代理 开启自动代理默认true,
    指定解决分布式事务模式XA模式;
    方法上添加注解@GlobalTransactional 
     手动代理:关闭自动代理;@Bean手动添加代理数据源
分库分表
1.相同的表结构,表名一样列名一样,事务尤为重要;sharding-jdbc
2.sharding-jdbc支持三种事务 local; xa(其他方法解决)@shardingtransactiontype;@transactional base(seata用的弱一致性)三种事务,
!!!!跨数据库跨进程
微服务项目
下订单 减少库存 扣账户钱 刷新订单状态
4个微服务
买的是什么商品
买几个
谁在买

最基础的seata-all依赖添加,自己.conf配置

seata-spring-boot依赖添加,application.yml添加配置
排除tcc模式,tcc要去找数据源,因为业务微服务不会使用数据源

seata分布式事务失效的场景??
为什么失效?
!!!(1)注册分支事务时没有传递全局事务id,要传递过去,可通过请求头,
通过拦截器,每次使用restemplate请求,放到请求头中;

(2)获取全局事务id 拦截器获取
1浏览器访问业务微服务,注册到TC服务器端,返回全局事务id,
可以收到全局事务id
2.订单、商品、账户微服务注册分支事务,要携带全局事务id,
此时手里没有全局事务id,
!!!seata某些版本的,自动代理使用Druid数据源可以,使用默认数据源可能不行。
!!!全局异常处理导致事务失效,全局异常处理之后,项目将不会出现显示异常,
此时TC认为正常,事务提交。

解决方案一:业务微服务做异常处理,后台服务不做异常处理
解决方案二:手动回滚,判断在不在全局事务中,执行rollback

sping-cloud-starter-alibaba-seata=依赖添加
aop实现,实际就是帮我们处理了,和上面的逻辑一样

远程调用换使用open feign实现 也完全兼容
添加依赖

!!!熔断降级 sentinel 导致分布式事务失效,手动回滚,在降级走的方法里
依赖注入 配置开启
openfeign 与sentinel,降级执行指定方法

seata的at的方式解决 保证弱一致性,要求用户体验
某个时间点或时间段数据不一致,但是数据最终会达到一致。不要求数据库支持xa协议
AT模式 95%场景使用极其推荐,来自于阿里巴巴中间团队提供的TXC服务演化为AT模式;

1.注册全局事务,tc返回全局事务id
2.tm给rm全局事务id,携带全局事务id,向tc注册分支事务id,返回给rm。
3.执行业务代码,直接提交事务。操作过程记录到日志中undo日志
4.向TC报告状态成功。
5.都执行成功,TM通知TC做事务提交,tc通知rm,实际删除undo日志
6.执行失败,TM通TC回滚事务,tc通知rm,按照日志记录回滚事务,恢复操作

全局锁
    什么时全局锁?
        全局锁是由表名和操作记录主键组成,存在文件
    解决并发场景
        rm操作数据库,提交事务的时候,tc端注册全局锁,如果发现已经存在,抛出异常
    释放全局锁
        二阶段提交,TM通知TC做事务提交,tc通知rm提交,放到内存队列
        异步处理,释放全局锁
实战:
多数据源
1.所有数据库添加支持AT的表结构,存储undo日志(线程等待,可以看到数据,弱一致性)
2.添加依赖,配置,自动代理,默认就是AT
3.你选择手动代理,添加seata默认代理数据源

分库分表
1.分库分表策略 shardingsphere 配置2个及以上数据源
sharding: table:表名,指定策略
2.所有数据库添加支持AT的表结构,存储undo日志(线程等待,可以看到数据,弱一致性)
3.添加依赖,配置,自动代理,默认就是AT
4.额外添加依赖,sharding Transaction Base Sesta At
原理是为了提供一个满足ShardingSphere提供的事务管理器的标准的一个事务管理器
5.resources下配置seata.conf配置
6.@Transactional@ShardingTransactionType(TransactionType.BASE)

微服务项目
1.所有数据库添加支持AT的表结构,存储undo日志(线程等待,可以看到数据,弱一致性)
2.添加依赖,编写配置,自动代理默认开启 ,默认就是AT,注意事务失效场景,是否传递,是否数据源版本
3.!!!注解@GlobalTransactional 写在controller层中在某些场景不生效,
有业务系统是可以。

4.注解@GlobalTransactional放到service层实现反而可能生效。
5.!!!切换数据源Druid时,yml添加配置如果指定数据源为spring_datasource_type,,seata不会自动代理不生效。直接向容器中添加Druiddatasource,seata在自动代理at模式会生效。

AT模式和XA模式在不同场景下解决比较????
微服务项目加分库分表(必须学会)
1.分表策略配置好
2.AT模式所需要的表结构
3.cloud——seata依赖,
4.seata——at依赖(第7点)
5.seata配置(druid数据源注意)
6.添加注解@GlobalTransactional
7.加在impl业务涉及到的分库分表微服务;seata.conf配置,
执行代码之前加入编码如下:TransactionTypeHolder.set(TransactionType.BASE)

TCC模式
不需要表结构支持,自己编写提交 回滚操作

Saga模式

seata分布式集群部署,实现高可用。
seata启动使用是存储数据的,所以集群要共享数据(全局事务id)。
可以放高性能redis 高可用可以放mysql,用来存储数据
1.window存储在mysql,运行自带的脚本4张表,
2.seata配置,application.yml,选择db连接
3.seata整合nacos,application.yml,注册到nacos上,微服务修改seata配置,使用nacos模式