醋醋百科网

Good Luck To You!

shardingjdbc-分布式事务实战案例

详细请参考官方文档:分布式事务 :: ShardingSphere

首先确定好自身引入的shradingjdbc版本号,因为我用的它的starter版本,所以没用这种core包的版本,所以yml配置还有分布式事务的配置也不尽相同,此处我以starter版本为阐述。



    org.apache.shardingsphere
    sharding-jdbc-spring-boot-starter
    4.0.0 

    org.apache.shardingsphere
    sharding-jdbc-core
    ${latest.release.version}

此外支持跨库事务必须配置对应的事务管理器的bean

package com.mode.technology.config;
 
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.jdbc.datasource.DataSourceTransactionManager;
import org.springframework.transaction.PlatformTransactionManager;
import org.springframework.transaction.annotation.EnableTransactionManagement;
 
import javax.sql.DataSource;
 
@Configuration
@EnableTransactionManagement
public class TransactionConfiguration {
 
    @Bean
    public PlatformTransactionManager txManager(final DataSource dataSource) {
        return new DataSourceTransactionManager(dataSource);
    }

}

核心概念

两阶段事务-XA

两阶段事务提交采用的是X/OPEN组织所定义的DTP模型,通过抽象出来的AP, TM, RM的概念可以保证事务的强一致性。 其中TMRM间采用XA的协议进行双向通信。 与传统的本地事务相比,XA事务增加了prepare阶段,数据库除了被动接受提交指令外,还可以反向通知调用方事务是否可以被提交。 因此TM可以收集所有分支事务的prepare结果,最后进行原子的提交,保证事务的强一致性。

Java通过定义JTA接口实现了XA的模型,JTA接口里的ResourceManager需要数据库厂商提供XA的驱动实现,而TransactionManager则需要事务管理器的厂商实现,传统的事务管理器需要同应用服务器绑定,因此使用的成本很高。 而嵌入式的事务管器可以以jar包的形式提供服务,同ShardingSphere集成后,可保证分片后跨库事务强一致性。

通常,只有使用了事务管理器厂商所提供的XA事务连接池,才能支持XA的事务。ShardingSphere整合XA事务时,分离了XA事务管理和连接池管理,这样接入XA时,可以做到对业务的零侵入。

实现原理查看官网文档:
https://shardingsphere.apache.org/document/legacy/4.x/document/cn/features/transaction/principle/2pc-xa-transaction/

Saga事务

Saga这个概念来源于三十多年前的一篇数据库论文Sagas ,一个Saga事务是一个有多个短时事务组成的长时的事务。 在分布式事务场景下,我们把一个Saga分布式事务看做是一个由多个本地事务组成的事务,每个本地事务都有一个与之对应的补偿事务。在Saga事务的执行过程中,如果某一步执行出现异常,Saga事务会被终止,同时会调用对应的补偿事务完成相关的恢复操作,这样保证Saga相关的本地事务要么都是执行成功,要么通过补偿恢复成为事务执行之前的状态。

自动反向补偿

Saga定义了一个事务中的每个子事务都有一个与之对应的反向补偿操作。由Saga事务管理器根据程序执行结果生成一张有向无环图,并在需要执行回滚操作时,根据该图依次按照相反的顺序调用反向补偿操作。Saga事务管理器只用于控制何时重试,何时补偿,并不负责补偿的内容,补偿的具体操作需要由开发者自行提供。

ShardingSphere采用反向SQL技术,将对数据库进行更新操作的SQL自动生成反向SQL,并交由saga-actuator执行,使用方则无需再关注如何实现补偿方法,将柔性事务管理器的应用范畴成功的定位回了事务的本源——数据库层面。
Seata柔性事务

Seata是阿里集团和蚂蚁金服联合打造的分布式事务框架,截止到0.5.x版本包含了AT事务和TCC事务。其中AT事务的目标是在微服务架构下,提供增量的事务ACID语意,让用户像使用本地事务一样,使用分布式事务,核心理念同ShardingSphere一脉相承。

Seata AT事务模型

Seata柔性事务

Seata是阿里集团和蚂蚁金服联合打造的分布式事务框架,截止到0.5.x版本包含了AT事务和TCC事务。其中AT事务的目标是在微服务架构下,提供增量的事务ACID语意,让用户像使用本地事务一样,使用分布式事务,核心理念同ShardingSphere一脉相承。

Seata AT事务模型

Seata AT事务模型包含TM(事务管理器),RM(资源管理器),TC(事务协调器)。其中TC是一个独立的服务需要单独部署,TM和RM以jar包的方式同业务应用部署在一起,它们同TC建立长连接,在整个事务生命周期内,保持RPC通信。 其中全局事务的发起方作为TM,全局事务的参与者作为RM ; TM负责全局事务的begin和commit/rollback,RM负责分支事务的执行结果上报,并且通过TC的协调进行commit/rollback。

支持功能

本地事务

功能

  • 完全支持非跨库事务,例如:仅分表,或分库但是路由的结果在单库中。
  • 完全支持因逻辑异常导致的跨库事务。例如:同一事务中,跨两个库更新。更新完毕后,抛出空指针,则两个库的内容都能回滚。
  • 不支持因网络、硬件异常导致的跨库事务。例如:同一事务中,跨两个库更新,更新完毕后、未提交之前,第一个库宕机,则只有第二个库数据提交。

支持情况

  • Sharding-JDBC和Sharding-Proxy原生支持本地事务(无需引入其它依赖)

测试新增

我这三个sql会根据zone字段落到不同的库,执行此接口发现数据库没有新增数据,说明事务确实回滚了

@ApiOperation(value = "测试分库分表插入-分布式事务-本地事务")
@GetMapping("/addTransactional")
@Transactional(rollbackFor = Exception.class)
public Tip addTransactional() {
    TOrder orderBJ = new TOrder();
    orderBJ.setUserId(100);
    orderBJ.setZone("bj");
    torderDao.insertSelective(orderBJ);
    TOrder orderSH = new TOrder();
    orderSH.setUserId(100);
    orderSH.setZone("sh");
    torderDao.insertSelective(orderSH);
    TOrder orderSZ = new TOrder();
    orderSZ.setUserId(100);
    orderSZ.setZone("sz");
    torderDao.insertSelective(orderSZ);
  
    int a= 1/0;
    return TipUtil.success();
}

二阶段事务-XA

ShardingSphere默认的XA事务管理器为Atomikos,在项目的logs目录中会生成xa_tx.log, 这是XA崩溃恢复时所需的日志,请勿删除。也可以通过在项目的classpath中添加jta.properties来定制化Atomikos配置项。具体的配置规则请参考Atomikos的官方文档。

功能

  • 支持数据分片后的跨库XA事务
  • 两阶段提交保证操作的原子性和数据的强一致性
  • 服务宕机重启后,提交/回滚中的事务可自动恢复
  • SPI机制整合主流的XA事务管理器,默认Atomikos,可以选择使用Narayana和Bitronix
  • 同时支持XA和非XA的连接池
  • 提供spring-boot和namespace的接入端

不支持项

  • 服务宕机后,在其它机器上恢复提交/回滚中的数据

需要引入对应的pom包


    org.apache.shardingsphere
    sharding-transaction-xa-core
    4.0.0

两阶段提交主要的原理是以上面的请求业务为例,当整个业务完成了之后只是第一阶段提交,在第二阶段提交之前会检查其他所有事务是否已经提交,如果前面出现了错误或是没有提交,那么第二阶段就不会提交,而是直接rollback操作,这样所有的事务都会做Rollback操作。上面的案例也可以通过二阶段xa事务来管理,改写下,相比第一种它对于容灾,务宕机重启后,它依然会提交/回滚中事务,可自动恢复

  @ApiOperation(value = "测试分库分表插入-分布式事务-xa事务")
    @GetMapping("/addTransactional")
    @Transactional(rollbackFor = Exception.class)
    @ShardingTransactionType(value = TransactionType.XA)
    public Tip addTransactional() {
        TOrder orderBJ = new TOrder();
        orderBJ.setUserId(100);
        orderBJ.setZone("bj");
        torderDao.insertSelective(orderBJ);

        TOrder orderSH = new TOrder();
        orderSH.setUserId(100);
        orderSH.setZone("sh");
        torderDao.insertSelective(orderSH);

        TOrder orderSZ = new TOrder();
        orderSZ.setUserId(100);
        orderSZ.setZone("sz");
        torderDao.insertSelective(orderSZ);

        int a= 1/0;
        return TipUtil.success();
    }

上述基于XA协议的全局事务,是属于强一致性事务,因为在全局事务中,只要有任何一个RM出现异常,都会导致全局事务回滚。同时,本地事务在Prepare阶段锁定资源时,如果有其他事务要要修改相同的数据,就必须要等待前面的事务完成,这本身是无可厚非的设计,但是由于多个RM节点是跨网络,一旦出现网络延迟,就导致该事务一直占用资源使得整体性能下降。所以它不适用于对并发有要求的情况

另外,在XA COMMIT阶段,如果其中一个RM因为网络超时没有收到数据提交的指令,会导致数据不一致,为了解决这个问题,很多开源分布式事务框架都会提供重试机制来保证数据一致性。

柔性事务-saga

  • 完全支持跨库事务
  • 支持失败SQL重试及最大努力送达
  • 支持反向SQL、自动生成更新快照以及自动补偿
  • 默认使用关系型数据库进行快照及事务日志的持久化,支持使用SPI的方式加载其他类型的持久化

不支持项

  • 暂不支持资源隔离
  • 暂不支持服务宕机后,自动恢复提交中的commit和rollback

支持情况

ShardingSphere的柔性事务已通过第三方SPI实现Saga事务,Saga引擎使用Servicecomb-Saga。

注意

  • 反向SQL需要主键,请确保在表结构中定义主键
  • 对于INSERT语句, 需要在SQL中显示插入主键值,如INSERT INTO ${table_name} (id, value, ...) VALUES (11111, '', ....) (其中id为表主键)
  • 若需要自动生成主键,可使用ShardingSphere的分布式主键。

实现原理官网参考:
https://shardingsphere.apache.org/document/legacy/4.x/document/cn/features/transaction/principle/base-transaction-saga/

柔性事务-seta

功能

  • 完全支持跨库分布式事务
  • 支持RC隔离级别
  • 通过undo快照进行事务回滚
  • 支持服务宕机后的,自动恢复提交中的事务

依赖

  • 需要额外部署Seata-server服务进行分支事务的协调

待优化项

  • ShardingSphere和Seata会对SQL进行重复解析

实现原理官网参考:
https://shardingsphere.apache.org/document/legacy/4.x/document/cn/features/transaction/principle/base-transaction-seata/


结尾

对于sega和seta这两种柔性事务的处理,我目前工作中还没遇到过,如果真的要用我肯定会优先看下阿里的seta框架,将它集成到我们项目中。

控制面板
您好,欢迎到访网站!
  查看权限
网站分类
最新留言