一、Seata是什么
Seata 是一款开源的分布式事务解决方案,致力于提供高性能和简单易用的分布式事务服务。Seata 将为用户提供了 AT、TCC、SAGA 和 XA 事务模式,为用户打造一站式的分布式解决方案。
官方文档
https://seata.io/zh-cn/docs/overview/what-is-seata.html
二、如何搭建服务端
1、下载服务端应用
https://github.com/seata/seata/releases https://github.com/seata/seata/releases/download/v1.6.1/seata-server-1.6.1.zip
2、配置启动
解压文件
配置
启动
三、如何使用客户端
1、添加依赖
<!-- seata--> <dependency> <groupId>com.alibaba.cloud</groupId> <artifactId>spring-cloud-starter-alibaba-seata</artifactId> </dependency>
2、添加配置
seata: service: vgroup-mapping: # 这里需要对事务组做映射,默认的分组名为 应用名称-seata-service-group,将其映射到default集群 # 这个很关键,一定要配置对,不然会找不到服务 book-service-seata-service-group: default grouplist: default: localhost:8868
book-service-seata-service-group,前边和应用名称保持一致。
3、启动类增加开启注解
@EnableAutoDataSourceProxy
4、新建undo_log数据表
Seata会分析修改数据的sql,同时生成对应的反向回滚SQL,这个回滚记录会存放在undo_log 表中。所以要求每一个Client 都有一个对应的undo_log表(也就是说每个服务连接的数据库都需要创建这样一个表。
CREATE TABLE `undo_log` ( `id` BIGINT(20) NOT NULL AUTO_INCREMENT, `branch_id` BIGINT(20) NOT NULL, `xid` VARCHAR(100) NOT NULL, `context` VARCHAR(128) NOT NULL, `rollback_info` LONGBLOB NOT NULL, `log_status` INT(11) NOT NULL, `log_created` DATETIME NOT NULL, `log_modified` DATETIME NOT NULL, `ext` VARCHAR(100) DEFAULT NULL, PRIMARY KEY (`id`), UNIQUE KEY `ux_undo_log` (`xid`, `branch_id`) ) ENGINE = InnoDB AUTO_INCREMENT = 1 DEFAULT CHARSET = utf8;
四、如何使用
需要执行分布式事务的操作上添加@GlobalTransactional注解。
涉及到的服务都需按照第三步配置,类似的Seata配置(服务名称不一样)。
@GlobalTransactional @Override public boolean doBorrow(int uid, int bid) { System.out.println(RootContext.getXID()); //1. 判断图书和用户是否都支持借阅 if(bookClient.bookRemain(bid) < 1) throw new RuntimeException("图书数量不足"); if(userClient.userRemain(uid) < 1) throw new RuntimeException("用户借阅量不足"); //2. 首先将图书的数量-1 if(!bookClient.bookBorrow(bid)) throw new RuntimeException("在借阅图书时出现错误!"); //3. 添加借阅信息 if(mapper.getBorrow(uid, bid) != null) throw new RuntimeException("此书籍已经被此用户借阅了!"); if(mapper.addBorrow(uid, bid) <= 0) throw new RuntimeException("在录入借阅信息时出现错误!"); //4. 用户可借阅-1 if(!userClient.userBorrow(uid)) throw new RuntimeException("在借阅时出现错误!"); //完成 return true; }