一、XA概述XA是由X/Open组织提出的分布式事务处理规范,它定义了全局事务管理器(Transaction Manager, TM)与局部资源管理器(Resource Manager, RM)之间的接口标准。XA协议采用两阶段提交(2PC)作为其核心实现机制。核心组件:
1、 应用程序(AP):发起事务的业务程序
2、 事务管理器(TM):协调全局事务,决定提交或回滚
3、 资源管理器(RM):管理具体资源(如数据库),执行实际的事务操作
组件交互时序图:
XID:XA事务使用XID作为全局唯一标识符,其结构如下:
public interface Xid {
int getFormatId();
byte[] getGlobalTransactionId();
byte[] getBranchQualifier();
}
- formatId:格式标识符
- globalTransactionId:全局事务ID
- branchQualifier:分支限定符
两阶段提交过程:
第一阶段:准备阶段
1、 TM向所有RM发送准备命令
2、 每个RM执行事务操作但不提交
3、 RM将事务信息持久化到日志
4、 RM返回准备结果(READY或ABORT)
第二阶段:提交阶段
根据准备阶段的结果:
- 全部RM准备成功:TM发送提交命令
- 任一RM准备失败:TM发送回滚命令
**二、Java中的XA的实现(JTA)**JTA是Java EE中定义的事务管理接口,支持XA协议:
public interface UserTransaction {
void begin() throws NotSupportedException, SystemException;
void commit() throws RollbackException, HeuristicMixedException,
HeuristicRollbackException, SecurityException,
IllegalStateException, SystemException;
void rollback() throws IllegalStateException, SecurityException,
SystemException;
void setRollbackOnly() throws IllegalStateException, SystemException;
int getStatus() throws SystemException;
void setTransactionTimeout(int seconds) throws SystemException;
}
XA数据源配置:
// 配置XA数据源
MysqlXADataSource mysqlXaDataSource = new MysqlXADataSource();
mysqlXaDataSource.setUrl("jdbc:mysql://localhost:3306/test");
mysqlXaDataSource.setUser("root");
mysqlXaDataSource.setPassword("password");
// 创建Atomikos连接池
AtomikosDataSourceBean xaDataSource = new AtomikosDataSourceBean();
xaDataSource.setXaDataSource(mysqlXaDataSource);
xaDataSource.setUniqueResourceName("mysqlXaDs");
xaDataSource.setPoolSize(5);
JTA管理XA事务示例:
// 获取JTA事务管理器
UserTransaction userTransaction = com.arjuna.ats.jta.UserTransaction.userTransaction();
try {
// 开始全局事务
userTransaction.begin();
// 获取XA连接
XAConnection xaConn1 = xaDataSource1.getXAConnection();
Connection conn1 = xaConn1.getConnection();
XAConnection xaConn2 = xaDataSource2.getXAConnection();
Connection conn2 = xaConn2.getConnection();
// 执行SQL操作
PreparedStatement ps1 = conn1.prepareStatement("UPDATE account SET balance = balance - ? WHERE id = ?");
ps1.setBigDecimal(1, new BigDecimal("100.00"));
ps1.setInt(2, 1);
ps1.executeUpdate();
PreparedStatement ps2 = conn2.prepareStatement("UPDATE account SET balance = balance + ? WHERE id = ?");
ps2.setBigDecimal(1, new BigDecimal("100.00"));
ps2.setInt(2, 2);
ps2.executeUpdate();
// 提交事务
userTransaction.commit();
} catch (Exception e) {
try {
userTransaction.rollback();
} catch (SystemException ex) {
ex.printStackTrace();
}
e.printStackTrace();
}
三、Seata XA模式在 Seata 定义的分布式事务框架内,利用事务资源(数据库、消息服务等)对 XA 协议的支持,以 XA 协议的机制来管理分支事务的一种 事务模式。
执行阶段:
- 可回滚:业务 SQL 操作放在 XA 分支中进行,由资源对 XA 协议的支持来保证 可回滚
- 持久化:XA 分支完成后,执行 XA prepare,同样,由资源对 XA 协议的支持来保证 持久化 (即,之后任何意外都不会造成无法回滚的情况)
完成阶段:
- 分支提交:执行 XA 分支的 commit
- 分支回滚:执行 XA 分支的 rollback
基本使用:XA 模式使用起来与 AT 模式基本一致,用法上的唯一区别在于数据源代理的替换:使用 DataSourceProxyXA
来替代 DataSourceProxy
。
public class DataSourceProxy {
@Bean("dataSourceProxy")
public DataSource dataSource(DruidDataSource druidDataSource) {
// DataSourceProxyXA for XA mode
return new DataSourceProxyXA(druidDataSource);
// DataSourceProxy for AT mode
// return new DataSourceProxy(druidDataSource);
}
}
更多内容,请参考官方文档:https://seata.apache.org/zh-cn/docs/dev/mode/xa-mode