多数据源下基于Atomikos实现事务回滚的方案咨询
多数据源事务回滚方案(Atomikos及替代实现)
一、使用Atomikos实现强一致事务回滚
Atomikos是轻量级JTA事务管理器,可实现跨多数据源的分布式事务,确保任一数据源操作失败时全部回滚。
1. 引入依赖
Maven项目添加以下依赖:
<dependency> <groupId>com.atomikos</groupId> <artifactId>transactions-jta</artifactId> <version>4.0.6</version> </dependency> <dependency> <groupId>com.atomikos</groupId> <artifactId>transactions-jdbc</artifactId> <version>4.0.6</version> </dependency> <!-- 对应数据库的XA驱动,以MySQL为例 --> <dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> <version>8.0.33</version> </dependency>
2. 配置XA数据源
将每个数据源包装为Atomikos兼容的XA数据源,示例为两个MySQL数据源:
@Configuration public class DataSourceConfig { @Bean(name = "dataSource1") public DataSource dataSource1() { AtomikosDataSourceBean xaDataSource = new AtomikosDataSourceBean(); MysqlXADataSource mysqlXaDataSource = new MysqlXADataSource(); mysqlXaDataSource.setUrl("jdbc:mysql://localhost:3306/db1?useSSL=false"); mysqlXaDataSource.setUser("root"); mysqlXaDataSource.setPassword("password"); xaDataSource.setXaDataSource(mysqlXaDataSource); xaDataSource.setUniqueResourceName("db1"); xaDataSource.setMinPoolSize(5); xaDataSource.setMaxPoolSize(20); return xaDataSource; } @Bean(name = "dataSource2") public DataSource dataSource2() { AtomikosDataSourceBean xaDataSource = new AtomikosDataSourceBean(); MysqlXADataSource mysqlXaDataSource = new MysqlXADataSource(); mysqlXaDataSource.setUrl("jdbc:mysql://localhost:3306/db2?useSSL=false"); mysqlXaDataSource.setUser("root"); mysqlXaDataSource.setPassword("password"); xaDataSource.setXaDataSource(mysqlXaDataSource); xaDataSource.setUniqueResourceName("db2"); xaDataSource.setMinPoolSize(5); xaDataSource.setMaxPoolSize(20); return xaDataSource; } }
3. 配置JTA事务管理器
适配Atomikos事务管理器与Spring的事务管理体系:
@Configuration @EnableTransactionManagement public class TransactionConfig { @Bean public UserTransaction userTransaction() throws SystemException { UserTransactionImp userTransactionImp = new UserTransactionImp(); userTransactionImp.setTransactionTimeout(300); return userTransactionImp; } @Bean public UserTransactionManager atomikosTransactionManager() { UserTransactionManager userTransactionManager = new UserTransactionManager(); userTransactionManager.setForceShutdown(false); return userTransactionManager; } @Bean(name = "jtaTransactionManager") public PlatformTransactionManager transactionManager(UserTransaction userTransaction, UserTransactionManager atomikosTransactionManager) { return new JtaTransactionManager(userTransaction, atomikosTransactionManager); } }
4. 业务层使用事务
在业务方法上标注@Transactional并指定JTA事务管理器:
@Service public class BizService { @Autowired private JdbcTemplate jdbcTemplate1; // 绑定dataSource1 @Autowired private JdbcTemplate jdbcTemplate2; // 绑定dataSource2 @Transactional(transactionManager = "jtaTransactionManager", rollbackFor = Exception.class) public void crossDataSourceOperation() throws Exception { // 操作第一个数据源 jdbcTemplate1.update("INSERT INTO table1 (name) VALUES (?)", "test1"); // 模拟第二个数据源操作失败 if (true) { throw new RuntimeException("Second data source operation failed"); } // 操作第二个数据源 jdbcTemplate2.update("INSERT INTO table2 (name) VALUES (?)", "test2"); } }
此时若第二个操作抛出异常,两个数据源的插入操作都会被回滚。
二、替代方案
1. 使用Narayana作为JTA提供者
Narayana是开源JTA事务管理器,配置逻辑与Atomikos一致:
- 引入Narayana依赖
- 配置XA数据源
- 适配Narayana事务管理器与Spring的
JtaTransactionManager
2. Spring Boot原生JTA支持
Spring Boot默认集成JTA,只需引入对应依赖(如Atomikos/Narayana),并在application.yml配置XA数据源:
spring: jta: atomikos: datasource: db1: xa-data-source-class-name: com.mysql.cj.jdbc.MysqlXADataSource unique-resource-name: db1 xa-properties: url: jdbc:mysql://localhost:3306/db1?useSSL=false user: root password: password db2: xa-data-source-class-name: com.mysql.cj.jdbc.MysqlXADataSource unique-resource-name: db2 xa-properties: url: jdbc:mysql://localhost:3306/db2?useSSL=false user: root password: password
Spring Boot会自动配置JTA事务管理器,业务层直接使用@Transactional即可。
3. 最终一致性方案(非强一致)
若对性能要求高且可接受最终一致,可采用本地消息表+MQ方案:
- 操作第一个数据源时,同步插入本地消息表
- 第一个操作成功后,发送MQ消息触发第二个数据源操作
- 若第二个操作失败,通过重试机制或人工补偿完成回滚/重试
- 定期清理已完成的消息,确保数据最终一致
注意事项
- 确保所有数据库支持XA协议(如MySQL需开启XA,部分轻量数据库可能不支持)
- XA事务会增加系统开销,避免在高并发场景下滥用
- 合理设置事务超时时间,避免长时间占用资源
内容的提问来源于stack exchange,提问作者Dharmin Patel
相关产品推荐
相关产品推荐

