Seata 是一款开源的分布式事务解决方案,提供高性能和简单易用的分布式事务服务。Seata 的设计目标是为用户提供一站式的分布式事务解决方案,它支持多种事务模式,其中 AT(Automatic Transaction)模式是最常用的一种。
Seata AT 模式简介
在 AT 模式下,Seata 通过代理 JDBC 驱动的方式,在不修改原有应用程序代码的基础上,实现对本地事务的增强。Seata 将一个事务分为两阶段:全局提交阶段和全局回滚阶段。AT 模式的核心组件包括:
- TC (Transaction Coordinator): 事务协调者,负责全局事务的管理。
- TM (Transaction Manager): 事务管理者,负责开始、提交或回滚全局事务。
- RM (Resource Manager): 资源管理者,负责分支注册、状态汇报以及分支的提交与回滚。
开启全局事务的过程
1. 客户端发起请求
客户端发起一个业务请求到应用服务层。
2. TM 开始全局事务
应用服务层调用 TM 开始一个全局事务。
3. RM 注册分支
当 TM 接收到开始全局事务的请求后,会通知 RM 进行分支注册。此时,RM 会将这个本地事务作为一个分支事务,并向 TC 注册。
4. 执行本地操作
RM 执行具体的 SQL 语句。在这个过程中,Seata 会对 SQL 语句进行拦截,生成并存储Undo Log。
5. 提交或回滚
如果所有分支事务都执行成功,TM 会通知 TC 进行全局提交;如果有任何一个分支事务失败,则 TM 通知 TC 进行全局回滚。
6. 清理
全局提交成功后,RM 会清理 Undo Log;如果全局回滚,则根据 Undo Log 进行数据恢复,并清理 Undo Log。
源码分析
开启全局事务
在 AT 模式中,全局事务的开启通常是由 Seata 的客户端 SDK 实现的。以下是一个简化的伪代码示例来说明如何在客户端启动全局事务:
// 创建一个全局事务管理器
GlobalTransaction globalTransaction = new DefaultGlobalTransaction();
try {
// 开始全局事务
globalTransaction.begin("xid", timeout);
// 获取资源管理器
ResourceManager rm = ResourceManagerHolder.get();
// 执行业务逻辑
executeBusinessLogic(rm);
// 提交全局事务
globalTransaction.commit();
} catch (Throwable e) {
// 回滚全局事务
globalTransaction.rollback();
}
在上述示例中,begin
方法用于启动一个全局事务,commit
和 rollback
分别用于提交和回滚全局事务。
分支注册
在执行业务逻辑时,每个数据库操作都会触发 RM 向 TC 注册分支事务:
private void executeBusinessLogic(ResourceManager rm) throws SQLException {
Connection conn = DataSourceProxy.getConnection();
conn.setAutoCommit(false); // 关闭自动提交
// 执行 SQL
PreparedStatement ps = conn.prepareStatement(sql);
ps.executeUpdate();
// 注册分支
BranchType branchType = BranchType.BASE;
String resourceId = "dataSourceId";
String clientId = "clientID";
Xid xid = globalTransaction.getXid();
rm.registerBranch(xid, resourceId, clientId, branchType, conn, sql, null);
conn.commit(); // 提交本地事务
}
在上面的例子中,registerBranch
方法用于向 TC 注册分支事务。这里需要注意的是,在 AT 模式下,本地事务的提交不会立即释放锁资源,而是会在全局提交之后才真正释放。
总结
以上是对 Seata AT 模式的简要介绍和源码分析。实际开发中还需要关注异常处理、配置文件的设置等方面的内容。对于深入理解 Seata 的工作原理,阅读其官方文档和源码是非常必要的。