SpringCloudAlibaba - 阿里分布式事务Seata
简介
Seata:简易可扩展的自治式分布式事务管理框架,其前身是fescar。是一种简单分布式事务的解决方案。 Seata给用户提供了AT、TCC、SAGA和XA事务模式,AT模式是阿里云中推出的商业版本GTS全局事务服务,目前Seata的版本已经到了1.0,我们本篇用是0.9版本。官网:https://github.com/seata/seata
Seata由3部分组成:
1.事务协调器(TC):维护全局事务和分支事务的状态,驱动全局提交或回滚,相当于LCN的协调者。
2.事务管理器(TM):定义全局事务的范围:开始全局事务,提交或回滚全局事务,相当于LCN中发起方。
3.资源管理器(RM):管理分支事务正在处理的资源,与TC进行对话以注册分支事务并报告分支事务的状态,并驱动分支事务的提交或回滚,相当于是LCN中的参与方。
白话文分析Seata实现原理:(与LCN基本一致,LCN前面博客有讲)
1. 发起方(TM)和我们的参与方(RM)项目启动之后和协调者TC保持长连接; 2. 发起方(TM)调用接口之前向 TC 获取一个全局的事务的id 为xid,注册到Seata中.Aop实现 3. 使用Feign客户端调用接口的时候,Seata重写了Feign客户端,在请求头中传递该xid。 4. 参与方(RM)从请求头中获取到该xid,方法执行完后不会立马提交,而是等待发起方调完接口后将状态提交到协调者,由协调者再告知参与方状态。
Seata环境搭建
下载对应Jar包并解压
首先在订单库和派单库(三中的业务库)分别导入conf目录下的undo_log.sql(专门做回滚用的),新建一个seata库,并把db_store.sql导入到seata库,该库主要是存放seata服务端的一些信息。
接下来修改register.conf,type改为nacos,nacos里面localhost后面加上:8848,详细如下图:

最后修改file.conf,store里面mode值改为db,并修改MySQL连接信息,注意库为上面建立的seata库:

双击bin目录下的seata-server.bat,启动成功如下:(需先启动Nacos)
客户端整合SeataServer
分布式事务解决方案有很多,如RabbitMQ最终一致性,RocketMQ事务消息,开源框架LCN,以及阿里Seata等。
业务场景:与前面RocketMQ解决分布式事务场景一致:

如图所示,相信我们都定过外卖,当提交订单后会在数据库生成一条订单,然后等待分配骑手送餐。
该业务在SpringCloud微服务架构拆分为两个服务,订单服务service-order和派单服务service-distribute,订单服务添加订单后,通过feign客户端调用派单服务的接口进行分配骑手,那么分布式事务问题就来了,当订单服务调用完第二行代码,派单接口执行完毕,咔嚓,第三行报了个错,那么订单接口会回滚,而派单则已提交事务,那么就造成数据不一致问题,故分布式事务问题,本文我们用Seata框架解决。
准备工作:分别建立订单表(左:order_table),派单表(右:distribute_table)


由于我们是SpringCloudAlibaba系列串讲,在前面博客建立好的service-impl添加如下依赖:
application.yml或者bootstrap.yml 添加Seata配置,且将上面修改好的file.conf和registry.conf拷贝到resources目录下:


订单服务,派单服务启动类分别移除默认DataSource配置:
在订单服务和派单服务分别建立配置文件:
接下来编写核心业务,首先编写派单服务
接下来编写订单服务:
分别启动Nacos,Seata,service-order,service-distribute,正常访问订单接口,则订单,派单表分别新增一条数据:



且两个控制台都会打印Commited日志:

异常访问订单接口,则订单,派单表事务都会回滚,都不会新增数据,控制台都会打印Rollbacked:


【总结】:目前主流分布式事务解决方案有很多,如RabbitMQ最终一致性,RocketMQ事务消息,LCN假关闭,阿里Seata,可以根据业务合理选择解决方案,毕竟先把技术Get到,项目技术选型也会多一种选择 ~
Last updated