Files
rikako-note/分布式事务/atomikos/atomikos.md
2024-04-07 23:18:16 +08:00

7.8 KiB
Raw Blame History

Atomikos

Getting Started

JTA

JTA(java transaction api)定义了java应用程序和特定平台的事务管理器进行交互的接口。类似与JDBC不同的平台实现了相同的JTA接口但是各个平台的底层实现JTA的方式不同。通过JTA可以不依赖事务管理器的提供平台来编写代码尽管各个平台实现不同但是都提供了相同的JTA接口。

分布式事务

2PC

2PC是一个在分布式系统中保证事务原子性的协议。在分布式事务涉及的所有节点中要么所有节点都对本地事务进行了提交或是所有节点都对本地事务进行了回滚。

在两阶段提交模型中,拥有两个角色:事务参与者和事务协调器。

第一阶段preparation phase
  1. Voting request事务协调器会向所有参与者都发送请求询问参与者是否可以提交事务
  2. Voting所有事务的参与者都对事务执行pre-execution操作并且根据执行状态决定是否事务可以提交。如果事务可以被提交那么参与者向协调器返回yes否则返回no
第二阶段commit/rollback phase
  1. 如果所有的参与者都向事务协调器返回了yes那么事务协调器会向所有参与者都发送commit命令
  2. 如果存在参与者向事务协调器返回了no或者存在参与者未在规定时间内向事务协调器返回是否可以提交事务那么事务协调器会向所有参与者都发送rollback命令

每个参与者在接收到commit或rollback命令后都会对本地事务执行命令相关的操作并且向事务协调器返回接收到命令的ack

2PC缺点
  1. 性能开销较大在两阶段提交协议中引入了许多的网络通信针对每个节点都会存在4次通信询问是否可以提交、相应是否可以提交、提交或回滚命令、对命令的ack这将会增加系统延迟对性能造成较大影响
  2. 单点故障在两阶段提交协议中coordinator扮演了重要角色如果coordinator宕机那么在coordinator恢复前所有参与者都不知道其是否应该提交或回滚事务直到coordinator恢复并发送commit或rollback命令。为了解决单点故障问题可以对coordinator采用主从集群来增加coordinator的可用性
  3. Blocking problem在2PC的第二阶段中如果存在一个参与者节点因为宕机或网络问题一直没有向coordinator返回其是否可以提交那么分布式系统会一直阻塞并等待其响应结果。这将会带来性能问题。可以通过引入超时机制来解决该问题当参与者未在指定时间内返回是否可以提交时coordinator会对所有节点执行回滚操作这样可以避免带来的阻塞问题。

3PC

为了更好解决2PC带来的上述问题3PC中引入了超时机制并且相对2PC新增了pre-commit阶段这样能够更好解决单点故障问题和阻塞问题。

第一阶段canCommit phase
  1. Commit Inquery事务协调器会向所有参与者发送询问请求询问参与者是否可以进入下一阶段即提交事务
  2. 参与者决策每个参与者基于其本地状态决定是否可以提交事务如果是返回can否则返回cannot
第二阶段PreCommit Phase
  1. 如果所有的参与者都返回了can那么事务协调器将会据欸的那个进入当前状态并向所有参与者都发送pre-commit命令
  2. partially pre-commit当接收到pre-commit命令后参与者会执行事务操作但是不会对事务进行提交并且向事务协调器发送ready-to-commit响应
第三阶段do-commit phase
  1. 当事务协调器收到所有参与者的ready-to-commit响应时其会向所有参与者发送commit指令
  2. 当参与者接收到commit指令时参与者会提交其本地事务
  3. 如果在第三阶段的过程中参与者向事务协调器发送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(); 
  } 
 
}

Spring Boot集成TransactionsEssentials

TransactionsEssentials 5.0及以上版本

如果要集成TransactionsEssentials 5.0及以上版本可以向pom中添加如下依赖

    <dependency>
      <groupId>com.atomikos</groupId>
      <artifactId>transactions-spring-boot-starter</artifactId>
    </dependency>

TransactionsEssentials 4.x

如果要集成4.x版本可以添加如下启动器该启动器为spring官方启动器

    <dependency>
      <groupId>org.springframework.boot</groupId>
      <artifactId>spring-boot-starter-jta-atomikos</artifactId>
    </dependency>

为atomikos指定日志级别

可以在properties中添加如下内容来指定atomikos的日志级别

logging.level.com.atomikos=DEBUG

在spring boot中配置atomikos属性

在spring boot中配置atomikos属性的示例如下所示

spring:
  jta:
    atomikos:
      properties:
        max-timeout: 900000