ByteJTA源码浅析&seata比较

594 阅读5分钟

[TOC]

笔者水平有限,如有理解错误,欢迎勘误。

阅读本文前建议先阅读下列关于分布式事务理论基础的系列博文: 田守枝Java技术博客之分布式事务

ByteJTA现状

由于ByteJTA的repo里几乎没有说明文档,技术社区也没有相关博文,故与作者进行了一些交流。

与作者交流原话:

byteJTA还在维护呢,不过由于大环境对XA/2PC谈虎色变,所以byteJTA目前优先级排在byteTCC之后。有bug肯定会改,后续还计划有一次大的优化升级呢。

ByteJTA源码包结构

javax.transaction.xa为Java对XA/JTA协议的支持包,其主要包括:

        javax.transaction.Status:事务状态,这个接口主要是定义一些表示事务状态的常量,此接口无需实现

        javax.transaction.Synchronization:同步

        javax.transaction.Transaction:事务

        javax.transaction.TransactionManager:事务管理器

        javax.transaction.UserTransaction:用于声明一个分布式事务

        javax.transaction.TransactionSynchronizationRegistry:事务同步注册

        javax.transaction.xa.XAResource:定义RM提供给TM操作的接口

        javax.transaction.xa.Xid:事务id

由于ByteJTA是对XA/JTA 规范的实现,所以基于此包接口进行开发,以下为ByteJTA的包结构:

├─bytejta-core  对JTA规范的拓展实现
│  └─src
│      └─main
│          └─java
│              └─org
│                  └─bytesoft
│                      ├─bytejta        transaction包下拓展的各个接口进行具体实现
│                      │  ├─logging
│                      │  │  ├─deserializer
│                      │  │  └─store
│                      │  ├─resource
│                      │  ├─strategy
│                      │  ├─supports
│                      │  │  ├─jdbc
│                      │  │  └─resource
│                      │  ├─work
│                      │  └─xa
│                      ├─common     工具类
│                      │  └─utils
│                      └─transaction        对JTA规范接口进行拓展
│                          ├─adapter
│                          ├─archive
│                          ├─aware      set注入标志接口
│                          ├─cmd        Runable、Callable类型任务导航
│                          ├─internal       TransactionResource、TransactionListener缓存、同步控制
│                          ├─logging        日志支持
│                          │  └─store
│                          ├─recovery
│                          ├─remote     远程节点代表
│                          ├─resource
│                          ├─supports
│                          │  ├─resource    扩展XAResource接口
│                          │  ├─rpc     RPC请求回应接口、拦截器接口
│                          │  └─serialize   序列化、反序列化接口
│                          ├─work       Runable task包装
│                          └─xa     TransactionID拓展接口
├─bytejta-supports      对transaction包下拓展的各个接口进行具体实现
│  └─src
│      └─main
│          ├─java
│          │  └─org
│          │      └─bytesoft
│          │          └─bytejta
│          │              └─supports
│          │                  ├─boot
│          │                  │  └─jdbc
│          │                  ├─internal
│          │                  ├─jdbc
│          │                  ├─jpa
│          │                  │  └─hibernate
│          │                  ├─resource
│          │                  │  ├─jdbc
│          │                  │  └─properties
│          │                  ├─rpc
│          │                  ├─serialize
│          │                  └─spring
│          └─resources
├─bytejta-supports-dubbo    dubbo对ByteJTA的通信支持
│  └─src
│      └─main
│          ├─java
│          │  └─org
│          │      └─bytesoft
│          │          └─bytejta
│          │              └─supports
│          │                  └─dubbo
│          │                      ├─config
│          │                      ├─ext
│          │                      ├─internal
│          │                      ├─serialize
│          │                      └─spi
│          └─resources
│              └─META-INF
│                  └─dubbo
└─bytejta-supports-springcloud      SpringCloud对ByteJTA的通信支持
    └─src
        └─main
            ├─java
            │  └─org
            │      └─bytesoft
            │          └─bytejta
            │              └─supports
            │                  └─springcloud
            │                      ├─config
            │                      ├─controller     transaction coordinator直接通过http协议暴露接口
            │                      ├─dbcp
            │                      ├─feign
            │                      ├─hystrix
            │                      ├─loadbalancer
            │                      ├─property
            │                      ├─rule
            │                      ├─serialize
            │                      └─web
            └─resources

说明:接口抽象都在org.bytesoft.transaction包中定义其XA/JTA规范接口进行了拓展,org.bytesoft.jta包下均为具体实现,另外bytejta-supports-dubbobytejta-supports-springcloud模块下均为通信支持。故上述目录着重说明接口定义。

ByteJTA对 XA/JTA协议的支持

Tips:以下涉及Spring或dubbo支持的只叙述Spring。

ByteJTA是对XA/JTA协议的完整实践,是一个标准的事务管理器(TM)。同时实现了事务协调器(TC)的集群管理(TC也分布在各个Application里,这一点与seata将TC抽成独立的server并计划做集群不同)。

持有远程TC的地址对象,以便通信:

public class RemoteCoordinatorRegistry {
	static final RemoteCoordinatorRegistry instance = new RemoteCoordinatorRegistry();

	/* host:port -> participant(url= host: port) */
	private final Map<RemoteAddr, RemoteCoordinator> physicalMap = new ConcurrentHashMap<RemoteAddr, RemoteCoordinator>();
	/* host:port -> host:application:port */
	private final Map<RemoteAddr, RemoteNode> mappings = new ConcurrentHashMap<RemoteAddr, RemoteNode>();
	/* application -> participant */
	private final Map<String, RemoteCoordinator> clusterMap = new ConcurrentHashMap<String, RemoteCoordinator>();

	/* invocation -> host:application:port */
	private final Map<InvocationDef, RemoteNode> invocationMap = new ConcurrentHashMap<InvocationDef, RemoteNode>();

具体Coordinator通信见org.bytesoft.bytejta.supports.springcloud.controller.TransactionCoordinatorController及其依赖。

SpringCloudConfiguration中委托了自定义TransactionManager,故可以使用Spring的@Transactional注解直接开启全局事务:

	public PlatformTransactionManager annotationDrivenTransactionManager() {
		org.springframework.transaction.jta.JtaTransactionManager jtaTransactionManager //
				= new org.springframework.transaction.jta.JtaTransactionManager();
		jtaTransactionManager.setTransactionManager(this.applicationContext.getBean(TransactionManager.class));
		jtaTransactionManager.setUserTransaction(this.applicationContext.getBean(UserTransaction.class));
		return jtaTransactionManager;
	}

具体事务控制见org.bytesoft.bytejta.TransactionManagerImpl

横向比较

通信

Seata

基于netty实现transaction coordinator与各applicationtransaction management之间的通信,并且通信部分被纳入core部分实现。

ByteJTA

构件core、support部分不负责实现通信,但考虑到集成到springcloud、dubbo通信的难度及成本,作者在ByteJTA-supports-dubbo和ByteJTA-supports-springcloud部分进行了集成。

笔者认为,通用构件或者框架的底层通信依赖于业务开发框架的web通信协议(http等),似乎有点不妥,性能和稳定性一定会受到影响,至于影响是否在可接受范围,笔者并没有进行详细测试。

resource manager

ByteJTA

基于数据库提供的XA接口实现,直接使用XAResource与数据库交互。从而实现多个数据库连接之间的事务管理。

seata 通过程序实现RM,不需要依赖数据库提供的XA实现。并且优化了XA的2PC第二阶段锁占用问题。

Transaction coordinator

ByteJTA

每个application均含有TC角色,并且通过RemoteCoordinatorRegistry缓存其他TC的地址信息。并通过springmvc或者dubbo通信。

由于数据库行锁被数据库本身RM所管理,所以其TC只负责协调各TM进行全局事务各阶段控制。

seata

将TC抽成独立Server单独部署,各application向其注册TM,并接受其协调。目前是单例版本,官方计划Server实现集群。

由于使用自己实现的RM进行本地事务的数据库交互,全局事务行锁信息则交由TC进行缓存(存储锁定行的keyid)。但由于自己实现了RM,RM不管理数据库锁定,在全局事务对某条数据A锁定的情况下,其他本地事务或者直接数据库操作无法感知数据A锁定,可以直接修改数据A,此时若全局事务回滚会造成脏读问题(seata 介绍中说最后提交的时候有判断,有预警方案,当前数据和undo_log表的后镜像不一致的话,log删不掉,需要人工介入,但在代码了没找到相应的说明)。

规范践行

ByteJTA

完整地践行了XA/JTA规范。

seata

在规范基础上提出新想法,优化事务二阶段提交锁定问题。

原创不易,觉得不错就点个赞以示鼓励吧!