1.seata是什么?
seata 是一款开源的分布式事务解决方案,致力于提供高性能和简单易用的分布式事务服务。Seata 将为用户提供了 AT、TCC、SAGA 和 XA 事务模式,为用户打造一站式的分布式解决方案。
2.本文中主要讲解seata的AT事务模式,参考文档,为官方文档,这里不讲解原理,有兴趣自己去看
https://seata.io/zh-cn/docs/overview/what-is-seata.html
3.下载和安装seata
3.1下载地址
https://github.com/seata/seata/releases
3.2按照图片下载对应的版本,我这里下载windows版的
如果是linux,解压命令是ar -xvzf xxx.tar.gz
3.3更改配置文件,解压文件之后可以在seata目录的conf目录下看到两个文件
3.4更改file.conf文件
3. 4.1 更改store里的mode为db
3.4.2更改db里的数据库连接参数,讲下面的用户名和密码更换为自己的用户名和密码
如果数据库是mysql8以上的,按以下方式更改
url更改为
jdbc:mysql://localhost:3306/seata?characterEncoding=utf8&useSSL=false&serverTimezone = GMT
数据库驱动driverClassName 更改为
com.mysql.cj.jdbc.Driver
其次,如果是seata的低版本还要将mysql的驱动包替换
将这个包替换到lib目录下
3.5更改registry.conf配置文件
3.6 1.0以后的版本去到以下网址下载配置文件
https://github.com/seata/seata/tree/develop/script/config-center
下载以下几个配置文件,config.txt,nacos-config.sh,nacos-config.py
其中nacos的点击nacos进去下载
然后更改配置config.txt里的配置,主要是数据库的四项
还有事务分组的配置,其中fsp_tx_group可以随便写,但是在项目中需要填一致
然后修改nacos-config.sh配置,将红圈中的修改为绝对路径,当然是windows下才这样,linux不需要
最后启动nacos,打开git的 Git Bash Here执行sh nacos-config.sh命令,将配置加载进nacos
3.7进入数据库,创建一个seata的数据库,执行以下连接里的sql
https://github.com/seata/seata/tree/develop/script/server/db
会得到以下三张表,走到这里基本上环境算是搭建好了
上一个简单的业务让大家用一下
新建三个工程,分别是订单(seata-order-service2001),仓储(seata-storage-service2002),账户(seata-account-service2003)
导入以下主要的pom依赖
<!--seata--> <dependency> <groupId>com.alibaba.cloud</groupId> <artifactId>spring-cloud-starter-alibaba-seata</artifactId> <exclusions> <exclusion> <artifactId>seata-all</artifactId> <groupId>io.seata</groupId> </exclusion> </exclusions> </dependency> <dependency> <groupId>io.seata</groupId> <artifactId>seata-all</artifactId> <version>1.4.1</version> </dependency>
上面的版本换成自己下载的版本号
将file.conf和registry.conf放入类路径下
修改application.yml文件,在以下位置填上之前配置中填写的分组名称
编写代码,这里dao什么sql我就不贴了,主要看主业务逻辑
在订单创建的业务代码上加上一个注解
@GlobalTransactional(name = "fsp-create-order",rollbackFor = Exception.class)
就可以解决分布式事务问题,代码如下,其中name可填可不填,最好填上唯一标识,方便查找问题
/** * 创建订单->调用库存服务扣减库存->调用账户服务扣减账户余额->修改订单状态 * 简单说:下订单->扣库存->减余额->改状态 */ @Override @GlobalTransactional(name = "fsp-create-order",rollbackFor = Exception.class) public void create(Order order) { log.info("----->开始新建订单"); //1 新建订单 orderDao.create(order); //2 扣减库存 log.info("----->订单微服务开始调用库存,做扣减Count"); storageService.decrease(order.getProductId(),order.getCount()); log.info("----->订单微服务开始调用库存,做扣减end"); //3 扣减账户 log.info("----->订单微服务开始调用账户,做扣减Money"); accountService.decrease(order.getUserId(),order.getMoney()); log.info("----->订单微服务开始调用账户,做扣减end"); //4 修改订单状态,从零到1,1代表已经完成 log.info("----->修改订单状态开始"); orderDao.update(order.getUserId(),0); log.info("----->修改订单状态结束"); log.info("----->下订单结束了,O(∩_∩)O哈哈~"); }
库存调用的是接口,我这里用的openFeign
@FeignClient(value = "seata-storage-service") public interface StorageService { @PostMapping(value = "/storage/decrease") CommonResult decrease(@RequestParam("productId") Long productId, @RequestParam("count") Integer count); } 还有账户的接口
@FeignClient(value = "seata-account-service") public interface AccountService { @PostMapping(value = "/account/decrease") CommonResult decrease(@RequestParam("userId") Long userId, @RequestParam("money") BigDecimal money); }
调用的其他业务逻辑我就不贴了,到这个程度,大家应该都会写,就是简单的一个项目,@GlobalTransactional注解只需要加在事务发起者上,其他的都不需要加注解