6.8 KiB
Atomikos
Getting Started
JTA
JTA(java transaction api)定义了java应用程序和特定平台的事务管理器进行交互的接口。类似与JDBC,不同的平台实现了相同的JTA接口,但是各个平台的底层实现JTA的方式不同。通过JTA,可以不依赖事务管理器的提供平台来编写代码,尽管各个平台实现不同,但是都提供了相同的JTA接口。
分布式事务
2PC
2PC是一个在分布式系统中保证事务原子性的协议。在分布式事务涉及的所有节点中,要么所有节点都对本地事务进行了提交,或是所有节点都对本地事务进行了回滚。
在两阶段提交模型中,拥有两个角色:事务参与者和事务协调器。
第一阶段(preparation phase)
- Voting request:事务协调器会向所有参与者都发送请求,询问参与者是否可以提交事务
- Voting:所有事务的参与者都对事务执行pre-execution操作,并且根据执行状态决定是否事务可以提交。如果事务可以被提交,那么参与者向协调器返回yes,否则返回no
第二阶段(commit/rollback phase)
- 如果所有的参与者都向事务协调器返回了yes,那么事务协调器会向所有参与者都发送commit命令
- 如果存在参与者向事务协调器返回了no,或者存在参与者未在规定时间内向事务协调器返回是否可以提交事务,那么事务协调器会向所有参与者都发送rollback命令
每个参与者在接收到commit或rollback命令后,都会对本地事务执行命令相关的操作,并且向事务协调器返回接收到命令的ack
2PC缺点
- 性能开销较大:在两阶段提交协议中,引入了许多的网络通信(针对每个节点,都会存在4次通信,询问是否可以提交、相应是否可以提交、提交或回滚命令、对命令的ack),这将会增加系统延迟,对性能造成较大影响
- 单点故障:在两阶段提交协议中,coordinator扮演了重要角色,如果coordinator宕机,那么在coordinator恢复前,所有参与者都不知道其是否应该提交或回滚事务,直到coordinator恢复并发送commit或rollback命令。为了解决单点故障问题,可以对coordinator采用主从集群来增加coordinator的可用性
- Blocking problem:在2PC的第二阶段中,如果存在一个参与者节点因为宕机或网络问题一直没有向coordinator返回其是否可以提交,那么分布式系统会一直阻塞并等待其响应结果。这将会带来性能问题。可以通过引入超时机制来解决该问题,当参与者未在指定时间内返回是否可以提交时,coordinator会对所有节点执行回滚操作,这样可以避免带来的阻塞问题。
3PC
为了更好解决2PC带来的上述问题,3PC中引入了超时机制,并且相对2PC新增了pre-commit阶段,这样能够更好解决单点故障问题和阻塞问题。
第一阶段(canCommit phase)
- Commit Inquery:事务协调器会向所有参与者发送询问请求,询问参与者是否可以进入下一阶段(即提交事务)
- 参与者决策:每个参与者基于其本地状态决定是否可以提交事务,如果是,返回can,否则返回cannot
第二阶段(PreCommit Phase)
- 如果所有的参与者都返回了can,那么事务协调器将会据欸的那个进入当前状态,并向所有参与者都发送pre-commit命令
- partially pre-commit:当接收到pre-commit命令后,参与者会执行事务操作,但是不会对事务进行提交,并且向事务协调器发送ready-to-commit响应
第三阶段(do-commit phase)
- 当事务协调器收到所有参与者的ready-to-commit响应时,其会向所有参与者发送commit指令
- 当参与者接收到commit指令时,参与者会提交其本地事务
- 如果在第三阶段的过程中,参与者向事务协调器发送abort,或是事务协调器向参与者发送abort,那么事务将会整体回滚
XA
XA(eXtended Architecture)是一个标准,用于访问位于同一全局事务内的多个后端数据库。
按照XA标准,XA事务管理器可以告诉数据库,作为全局事务的一部分,哪些工作正在哪个事务范围内执行。并且,XA事务管理器还会告诉数据库在本地事务结束后,如何处理两阶段事务提交(2PC)。XA事务管理器同时还负责将数据库中处于pending状态的事务进行恢复。
XA的好处
因为XA是一种标准,故而作为全局事务的一部分,任何特定实现的数据库driver实现都可以和任一其他平台的事务管理器一起工作,XA基于两阶段提交提供了将不同平台的数据库driver和事务管理器整合到一起的能力。
TransactionsEssentials
底层实现
Atomikos通过模块化的方式进行设计,其存在一个叫做icatch的内核,内核提供了专有api。许多transactional service都基于icatch内核提供的api构建,例如JTA,基于icatch api实现了JTA api。
atomikos是嵌入式的transaction manager,其是嵌入java应用的,并不需要启动独立的transaction manager服务。
通过Atomikos编码
在编写代码时,通常仅使用JTA api,并不需要使用icatch api。
为了初始化transaction manager,需要创建com.atomikos.icatch.jta.UserTransactionManager实例,并且调用实例的init方法,并且在应用关闭时,需要调用事务管理器的close方法。
com.atomikos.icatch.jta.UserTransactionManager实现了javax.transaction.TransactionManager,可以通过begin()、commit()、rollback()来控制事务。
在初始化事务时,会读取classpath的根路径读取jta.properties文件。
简单的jta示例
import com.atomikos.icatch.jta.UserTransactionManager;
import com.atomikos.jdbc.AtomikosDataSourceBean;
import javax.jta.TransactionManager;
import javax.sql.DataSource;
public class AtomikosExample {
// Atomikos implementations
private static UserTransactionManager utm;
private static AtomikosDataSourceBean adsb;
// Standard interfaces
private static TransactionManager tm;
private static DataSource ds;
// initialize resources
private static void init() {
utm = new UserTransactionManager();
utm.init();
tm = utm;
adsb = ...; // omitted for clarity
ds = adsb;
}
// release resources
private static void shutdown() {
adsb.close();
utm.close();
}
public static void main(String[] args) {
init();
tm.begin();
Connection c = ds.getConnection();
// use connection to execute SQL
c.close();
tm.commit();
shutdown();
}
}