分布式事务解决方案1--使用Atomikos分布式事务(事务强一致方案)
Posted on 2020-11-18 15:34 work hard work smart 阅读(543) 评论(0) 收藏 举报分布式事务基本概念可参考分布式事务介绍
这里我们介绍Atomikos分布式事务,它是基于XA的分布式事务
1、准备-创建数据库

在192.168.127.129和192.168.127.134分别创建数据库xa_129和xa_134, 表分别为xa_129, xa_134, 表结构都是id和name。
2、创建工程
1) 创建Spring Boot工程

命名为my-xa-demo

选择需要的依赖后点击完成

3、添加依赖
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-jta-atomikos</artifactId>
</dependency>
4、使用MyBatis-generator生成数据库相关的文件

5、配置数据源
1) ConfigDb129
/**
* 数据源配置。RM资源管理器
*/
@Configuration
@MapperScan(value = "com.example.myxademo.db129.dao", sqlSessionFactoryRef = "sqlSessionFactoryBean129")
public class ConfigDb129 {
@Bean("db129")
public DataSource db129(){
MysqlXADataSource xaDs = new MysqlXADataSource();
xaDs.setUser("root");
xaDs.setPassword("123456");
xaDs.setUrl("jdbc:mysql://192.168.127.129:3306/xa_129");
AtomikosDataSourceBean atomikosDataSourceBean = new AtomikosDataSourceBean();
atomikosDataSourceBean.setXaDataSource(xaDs);
atomikosDataSourceBean.setUniqueResourceName("db129");
return atomikosDataSourceBean;
}
@Bean("sqlSessionFactoryBean129")
public SqlSessionFactoryBean sqlSessionFactoryBean(@Qualifier("db129") DataSource dataSource) throws IOException {
SqlSessionFactoryBean sqlSessionFactoryBean = new SqlSessionFactoryBean();
sqlSessionFactoryBean.setDataSource(dataSource);
ResourcePatternResolver resourcePatternResolver = new PathMatchingResourcePatternResolver();
sqlSessionFactoryBean.setMapperLocations(resourcePatternResolver.getResources("mybatis/db129/*.xml"));
return sqlSessionFactoryBean;
}
/**
* JTA 事务管理器
* @return
*/
@Bean("xaTransaction")
public JtaTransactionManager jtaTransactionManager(){
UserTransaction userTransaction = new UserTransactionImp();
UserTransactionManager userTransactionManager = new UserTransactionManager();
return new JtaTransactionManager(userTransaction, userTransactionManager);
}
}
并且定义了事务管理器
ConfigDb134
/**
* 数据源配置。RM资源管理器
*/
@Configuration
@MapperScan(value = "com.example.myxademo.db134.dao", sqlSessionFactoryRef = "sqlSessionFactoryBean134")
public class ConfigDb134 {
@Bean("db134")
public DataSource db134(){
MysqlXADataSource xaDs = new MysqlXADataSource();
xaDs.setUser("root");
xaDs.setPassword("123456");
xaDs.setUrl("jdbc:mysql://192.168.127.134:3306/xa_134");
AtomikosDataSourceBean atomikosDataSourceBean = new AtomikosDataSourceBean();
atomikosDataSourceBean.setUniqueResourceName("db134");
atomikosDataSourceBean.setXaDataSource(xaDs);
return atomikosDataSourceBean;
}
@Bean("sqlSessionFactoryBean134")
public SqlSessionFactoryBean sqlSessionFactoryBean(@Qualifier("db134") DataSource dataSource) throws IOException {
SqlSessionFactoryBean sqlSessionFactoryBean = new SqlSessionFactoryBean();
sqlSessionFactoryBean.setDataSource(dataSource);
ResourcePatternResolver resourcePatternResolver = new PathMatchingResourcePatternResolver();
sqlSessionFactoryBean.setMapperLocations(resourcePatternResolver.getResources("mybatis/db134/*.xml"));
return sqlSessionFactoryBean;
}
}
6、创建服务
@Service
public class XAService {
@Resource
private XA129Mapper xa129Mapper;
@Resource
private XA134Mapper xa134Mapper;
@Transactional(transactionManager = "xaTransaction")
public void testXA(){
XA129 xa129 = new XA129();
xa129.setId(1);
xa129.setName("XA_129");
xa129Mapper.insert(xa129);
XA134 xa134 = new XA134();
xa134.setId(1);
xa134.setName("XA_134");
xa134Mapper.insert(xa134);
}
}
7、测试
@SpringBootTest
class MyXaDemoApplicationTests {
@Test
void testXA() {
xaService.testXA();
}
}
运行后,可以发现两个数据库多插入成功了。

8、模拟事务回滚
将两个表的数据清空,并且修改name字段的长度为1,重新运行测试

可以发现,两个表都没有插入成功。
作者:Work Hard Work Smart
出处:http://www.cnblogs.com/linlf03/
欢迎任何形式的转载,未经作者同意,请保留此段声明!
浙公网安备 33010602011771号