在《Spring Boot JDBC多数据源》中,我们已经可以使用多个数据源为服务提供持久化能力。在单个数据源的时候,我们可以借助数据库本身的事务机制,保持数据的一致性,那么,在多个数据源的情况下,我们如何保证数据的一致性呢?这一章节我们来了解一下。
什么是分布式事务
要了解多个数据源如何保持数据一致性时,我们先来看一个概念:分布式事务。究竟什么是分布式事务呢?
简单来说,一个事务包含多个操作,多个操作操作了多个数据源,这样的事务称为分布式事务。
什么是JTA
说起JTA,我们就需要说一下XA协议了。
- XA协议:XA是X/Open DTP组织(X/Open DTP group)定义的包含:两阶段提交协议,三阶段提交协议,XA被许多数据库(如Oracle、DB2、SQL Server、MySQL)和中间件等工具(如CICS 和 Tuxedo)支持 。
- JTA:JTA(Java Transaction API),是J2EE的编程接口规范,它是XA协议的JAVA实现。某种程度上,可以认为JTA规范是XA规范的Java版。
- Atomikos:Atomikos是一个分布式事务管理器,是JTA / XA的具体实现,提供的功能比JTA / XA所要求的更多
JTA示意图:

Spring Boot JTA实例
引入pom依赖
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-jta-atomikos</artifactId>
</dependency>
配置文件
spring:
datasource:
primary:
uniqueResourceName: primary
xaDataSourceClassName: com.mysql.cj.jdbc.MysqlXADataSource
xaProperties:
url: jdbc:mysql://ip:port/springboot_demo?characterEncoding=utf-8&allowMultiQueries=true&autoReconnect=true
user: root
password: xxxxxxx
exclusiveConnectionMode: true
minPoolSize: 3
maxPoolSize: 10
second:
uniqueResourceName: second
xaDataSourceClassName: com.mysql.cj.jdbc.MysqlXADataSource
xaProperties:
url: jdbc:mysql://ip:port/springboot_demo_2?characterEncoding=utf-8&allowMultiQueries=true&autoReconnect=true
user: root
password: xxxxxxx
exclusiveConnectionMode: true
minPoolSize: 3
maxPoolSize: 10
数据源配置
@Configuration
public class DataSourceConfig {
@Bean(initMethod = "init", destroyMethod = "close", name = "primaryDataSource")
@ConfigurationProperties(prefix = "spring.datasource.primary")
@Primary
public DataSource primaryDataSource() {
return new AtomikosDataSourceBean();
}
@Bean(initMethod = "init", destroyMethod = "close", name = "secondDataSource")
@Qualifier("secondDataSource")
@ConfigurationProperties(prefix = "spring.datasource.second")
public DataSource secondDataSource() {
return new AtomikosDataSourceBean();
}
}
JdbcTemplate配置
@Configuration
public class JdbcTemplateConfig {
@Bean(name = "primaryJdbcTemplate")
public JdbcTemplate primaryJdbcTemplate(
@Qualifier("primaryDataSource") DataSource dataSource) {
return new JdbcTemplate(dataSource);
}
@Bean(name = "secondJdbcTemplate")
public JdbcTemplate secondaryJdbcTemplate(
@Qualifier("secondDataSource") DataSource dataSource) {
return new JdbcTemplate(dataSource);
}
}
统一事务配置
@Configuration
public class TransacationManagerConfig {
@Bean
public UserTransaction userTransaction() throws SystemException {
UserTransaction userTransaction = new UserTransactionImp();
userTransaction.setTransactionTimeout(10000);
return userTransaction;
}
@Bean(name = "atomikosTransactionManager", initMethod = "init", destroyMethod = "close")
public TransactionManager atomikosTransacationManager() throws Throwable{
UserTransactionManager userTransactionManager = new UserTransactionManager();
userTransactionManager.setForceShutdown(false);
return userTransactionManager;
}
@Bean(name = "transacationManager")
public PlatformTransactionManager transactionManager() throws Throwable {
UserTransaction userTransaction = new UserTransactionImp();
JtaTransactionManager manager = new JtaTransactionManager(userTransaction, atomikosTransacationManager());
return manager;
}
}
测试
由于是在上个工程
《JDBC读数据源》
https://gitee.com/pftian/spring-boot-learning/tree/master/spring-boot-jdbc-multiple-datasource
的基础上做的改造,我们直接编写测试用例。
@SpringBootTest(classes = JDBCApplication.class)
public class JTATest {
@Autowired
UserService userService;
@Autowired
LogService logService;
@Test
@Transactional
public void testJTATransaction() {
User user = new User();
Log log = new Log();
user.setBorthday(new Date());
user.setName("jta");
log.setLogTime(new Date());
log.setIp("22222");
log.setMethod("xxxxx");
userService.save(user);
logService.save(log);
// 手动制造异常
int a = 100/0;
}
}
伙伴们,行动起来,加油!!!
源码地址:Spring Boot Learning: 学习springboot中的各个组件,编写示例工程 运行spring-boot-jdbc-jta工程。
© 版权声明
文章版权归作者所有,未经允许请勿转载。
相关文章
暂无评论...