1、AT 模式简介
AT 模式官网已经给出了很详细的介绍,可以直接看官网
http://seata.io/zh-cn/docs/dev/mode/at-mode.html
2、建立项目
涉及的代码过多,这里只对几个关键的步骤进行说明,完整代码可以到 git 上下载,AT 模式在 master 分支上,数据库脚本在 script 目录下
https://gitee.com/WylLoveX/seata.git
2.1、maven 依赖
这里我们建立一个 spring boot 项目,基于 2.2.5.RELEASE 版本,引入 seata 和 nacos 需要的依赖。
spring-cloud-starter-alibaba-seata 内部封装了 seata 分布式事务的 XID 的传递,引入直接使用,如果不用这个组件,就只能自己解决 XID 传递的问题;
seata-spring-boot-starter 的版本号和 seata 版本保持一致;
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.2.5.RELEASE</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
<version>2.2.5.RELEASE</version>
</dependency>
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-seata</artifactId>
<version>2.2.5.RELEASE</version>
<exclusions>
<exclusion>
<groupId>io.seata</groupId>
<artifactId>seata-spring-boot-starter</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>io.seata</groupId>
<artifactId>seata-spring-boot-starter</artifactId>
<version>1.3.0</version>
<exclusions>
<exclusion>
<groupId>com.alibaba</groupId>
<artifactId>druid</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid</artifactId>
<version>1.1.21</version>
</dependency>
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
<version>2.2.5.RELEASE</version>
</dependency>
</dependencies>
2.2、yml 配置
先配置将服务注册到 nacos,然后对 seata 进行配置,seata 的 tx-service-group 的值,对应了 seata 事务组的配置,例如,我这个服务的 seata.tx-service-group 的值为 order_group,那就要和 seata 中的配置对应
service.vgroupMapping.order_group=default
server:
port: 8080
spring:
datasource:
url: jdbc:mysql://10.116.11.110:3306/order?useUnicode=true&characeterEncoding=utf-8&serverTimezone=UTC&useSSL=false
username: root
password: root
driver-class-name: com.mysql.jdbc.Driver
application:
name: order
cloud:
nacos:
discovery:
server-addr: 10.116.11.110:8848
logging:
level:
io:
seata: debug
mybatis:
# Mybatis配置Mapper路径
mapper-locations: classpath:mapper/**/*.xml
seata:
tx-service-group: order_group
config:
type: nacos
nacos:
server-addr: 10.116.11.110:8848
group: SEATA_GROUP
2.3、数据源配置
然后我们需要设置 mybatis 使用 seata 的数据源代理
import com.alibaba.druid.pool.DruidDataSource;
import io.seata.rm.datasource.DataSourceProxy;
import org.apache.ibatis.session.SqlSessionFactory;
import org.mybatis.spring.SqlSessionFactoryBean;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.boot.jdbc.DataSourceBuilder;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.io.support.PathMatchingResourcePatternResolver;
import javax.sql.DataSource;
/**
* @author Mr.Wen
* @version 1.0
* @date 2021-10-27 19:06
*/
@Configuration
public class DataSourceProxyConfig {
@Value("${mybatis.mapper-locations}")
private String mapperLocations;
@Bean
@ConfigurationProperties(prefix = "spring.datasource")
public DataSource druidDatasource(){
return new DruidDataSource();
}
@Bean
public SqlSessionFactory sqlSessionFactory(DataSource datasource) throws Exception{
SqlSessionFactoryBean sessionFactoryBean = new SqlSessionFactoryBean();
sessionFactoryBean.setDataSource(new DataSourceProxy(datasource));
sessionFactoryBean.setMapperLocations(new PathMatchingResourcePatternResolver().getResources(mapperLocations));
return sessionFactoryBean.getObject();
}
}
2.4、undo_log
AT 模式下,每个服务对应的库中,都要建立 undo_log 表
2.5、项目启动
启动需要几个注解,因为我们自己建立了数据源,所以就直接剔除 spring boot 的数据源自动配置
/**
* @author Mr.Wen
* @version 1.0
* @date 2021-10-21 16:59
*/
@SpringBootApplication(exclude = DataSourceAutoConfiguration.class)
@EnableDiscoveryClient
@Import(DataSourceProxyConfig.class)
public class OrderApplication {
public static void main(String[] args){
SpringApplication.run(OrderApplication.class);
}
}
3、使用
事务发起端添加全局事务注解 @GlobalTransactional,同时注意不要捕获异常,否则事务不会回滚
事务发起端:
事务参与:
、
4、注意
这个模式的核心是 undo_log 表,这个表记录的操作的数据在事务提交前的状态和事务提交后的状态,本地事务会将 undo_log 和我们的数据库操作一起提交,所以,我们在 3 中的全局事务发起者中打个断点,会发现事务已经是提交了的,出错回滚的话,其实并不是我们理解的 rollback,因为我们修改数据的事务已经提交了,seata 的回滚就是读取 undo_log 表的操作日志,找到对应数据的事务提交前的记录,将他重新设置为事务提交前的样子。全局事务回滚或者提交后,会删除 undo_log 中对应的记录。
分布式事务如果回滚失败,可以检查下 XID 是否传递成功。
欢迎来到这里!
我们正在构建一个小众社区,大家在这里相互信任,以平等 • 自由 • 奔放的价值观进行分享交流。最终,希望大家能够找到与自己志同道合的伙伴,共同成长。
注册 关于