JTA实现分布式事务
开门见山
关于事务的基本概念和介绍请参阅另一篇博客事务处理机制与协议,这里着重讲解如何在Spring中基于JTA(Java Transaction API)实现分布式事务并实践。
Spring Boot除了对非XA的事务进行了封装处理,并提供了注解@Transactional的方式实现事务管理,也对多XA资源的分布式JTA事务提供了很好的支持,通常可选的内嵌事务管理器有Atomikos
和Bitronix
,任意选择一个作为实现XA事务管理的管理器即可。
接下来就分别介绍利用Spring Boot实现非XA和XA的事务处理。
Spring对非XA事务的实现
使用Spring Boot实现非XA事务非常简单,只需要简单的两步即可:
- 在构建脚本文件中加入依赖
org.springframework.boot:spring-boot-starter-jdbc
。 - 无论采用基本的
JdbcTemplate
或封装的JPA
与数据库进行交互,只需要在具体方法上加注解@Transactional(org.springframework.transaction.annotation.Transactional)
。
这样就将该块的操作序列当作一个事务单元进行管理,任何失败或异常都将导致所有操作序列回滚,一个具体的简单Demo可参见Transaction Demo,另外,如果注解加在类名上,则代表该类中每个方法都将作为一个事务单元被管理。
采用Atomikos事务管理器
Atomikos是一款JTA事务管理器的开源库,能够Embedded到Spring Boot中,可以通过添加依赖spring-boot-starter-jta-atomikos
,然后Spring Boot会自动配置Atomikos并下载其依赖库,默认的事务日志文件会被写在项目下的transaction-logs
文件目录下的日志文件中,可以通过配置spring.jta.log-dir
来指定日志目录。可以设置spring.jta.atomikos.properties
读取相应的配置文件。可以参阅完成的详细信息AtomikosProperties Javadoc。
为了保证多个事务管理器能够正常安全地协调相同的资源管理器,每一个Atomikos实例必须配置一个唯一的ID,默认值为当前所在机器IP,通常在产品环境中,可以为每个应用程序实例配置spring.jta.transaction-manager-id
为不同的值。
在Spring Boot中,可以自定义在应用程序配置文件中配置AtomikosProperties参数:
一个具体的Atomikos分布式事务管理示例可参见Atomikos Demo。
采用Bitronix事务管理器
Bitronix是一款JTA事务管理器的开源库,可以通过添加依赖spring-boot-starter-jta-bitronix
,然后Spring Boot会自动配置Bitronix,默认的事务日志文件会被写在项目下的transaction-logs
文件目录下的part1.btm
和part2.btm
中,可以通过配置spring.jta.log-dir
来指定日志目录。可以设置spring.jta.bitronix.properties
读取相应的配置文件,相当于自定义配置bitronix.tm.configuration
实例。
为了保证多个事务管理器能够正常安全地协调相同的资源管理器,每一个Bitronix实例必须配置一个唯一的ID,默认值为当前所在机器IP,通常在产品环境中,可以为每个应用程序实例配置spring.jta.transaction-manager-id
为不同的值。
在Spring Boot集成应用中,可以根据自定义需求在应用程序配置文件中配置以下参数:
一个具体的Bitronix分布式事务管理示例可参见Bitronix Demo。
混合XA/非XA事务的JMS连接
当使用JTA时,默认情况下,主要的JMSConnectionFactory
实例会被自动加入到XA资源中,并参与XA事务。如果在某些情况下,如JMS处理时间较长,超过了XA的Timeout时间,则需要在处理JMS时不使用XA的ConnectionFactory
,只需在注入时使用nonXaJmsConnectionFactory
即可,以下是代码示例:
General Databases
针对不同的数据库可能需要设置一些不同的参数开启XA功能,比如Postgresql,需要设置参数max_prepared_transactions
,整型值,它决定能够同时处于prepared状态的事务的最大数目,0表示关闭prepared事务的特性,该值通常应该和max_connections的值一样大。
如果使用AWS的Postgresql RDS数据库,则需要在Parameter Group中设置该值,否则默认会为0,表示关闭XA功能。
References