亚马逊AWS官方博客

Amazon Aurora分库分表架构下集成Sharding-JDBC实现分布式事务

1.前言

1.1 Amazon Aurora介绍

Amazon Aurora是亚马逊云科技自研的一项关系数据库服务,它在提供和开源数据库MySQL、PostgreSQL的完好兼容性同时,也能够提供和商业数据库媲美的性能和可用性。性能方面,Aurora MySQL能够支持到与开源标准MySQL同等配置下五倍的吞吐量,Aurora PostgreSQL能够支持与开源标准PostgreSQL同等配置下三倍的吞吐量的提升。在扩展性的角度,Aurora在存储与计算、横向与纵向方面都进行了功能的增强和创新。

Aurora的最大数据存储量现在支持多达128TB,而且可以支持存储的动态收缩。计算方面,Aurora提供多个读副本的可扩展性配置支持一个区域内15个多达15个读副本的扩展,提供多主的架构来支持同一个区域内4个写节点的扩展,提供Serverless无服务器化的架构实例级别的秒级纵向扩展,提供全球数据库来实现数据库的低延迟跨区域扩展。
随着用户数据量的增长,Aurora已经提供了很好的扩展性,那是否可以进一步增强更多的数据量、更多的并发访问能力呢?您可以考虑利用分库分表的方式,来支持底层多个Aurora集群的配置。基于此,包含这篇博客在内的系列博客会进行相应的介绍,旨在为您进行分库分表时代理或者JDBC的选择提供参考。

1.2 ShardingSphere介绍

ShardingSphere是一套开源的分布式数据库中间件解决方案组成的生态圈,它由Sharding-JDBC、Sharding-Proxy 和 Sharding-Sidecar这3款相互独立的产品组成。

A B C D
1 对比项 ShardingSphere-JDBC ShardingSphere-Proxy ShardingSphere-Sidecar
2 数据库 任意 MySQL/PostgreSQL MySQL/PostgreSQL
3 连接消耗数
4 异构语言 仅 Java 任意 任意
5 性能 损耗低 损耗略高 损耗低
6 无中心化
7 静态入口

1.2.1 Sharding-JDBC特点

  • 它使用客户端直连数据库,以 jar 包形式提供服务。
  • 无需额外部署和依赖,可理解为增强版的JDBC 驱动,完全兼容JDBC和各种ORM框架。
  • 适用于任何基于JDBC的ORM框架,如:JPA, Hibernate, Mybatis或直接使用JDBC。
  • 支持任何第三方的数据库连接池,如:DBCP, C3P0, BoneCP, HikariCP等;
  • 支持任意实现JDBC 规范的数据库,目前支持MySQL,PostgreSQL,Oracle,SQLServer以及任何可使用 JDBC 访问的数据库。
  • 采用无中心化架构,与应用程序共享资源,适用于 Java 开发的高性能的轻量级 OLTP 应用

1.2.2 Sharding-JDBC与应用集成的架构

1.2.3 Sharding-JDBC基本术语

数据节点Node:数据分片的最小单元,由数据源名称和数据表组成,比如:ds_0.product_order_0。
真实表:在分片的数据库中真实存在的物理表,比如商品订单表 product_order_0、product_order_1、product_order_2。
逻辑表:水平拆分的数据库(表)的相同逻辑和数据结构表的总称,比如商品订单表 product_order_0、product_order_1、product_order_2,逻辑表就是product_order。
绑定表:指分片规则一致的主表和子表,比如product_order表和product_order_item表,均按照order_id分片,则此两张表互为绑定表关系,绑定表之间的多表关联查询不会出现笛卡尔积关联,关联查询效率将大大提升
广播表:指所有的分片数据源中都存在的表,表结构和表中的数据在每个数据库中均完全一致,适用于数据量不大且需要与海量数据的表进行关联查询的场景,例如:字典表、配置表。

1.3 分布式事务介绍

传统单体应用场景下,系统的数据保存在一个数据库实例的一个Database,通常场景的关系数据库自动都提供了事务保证,并且这种情况下的事务称为本地事务能保证原子性、一致性、隔离性、持久性(ACID特性)。
随着业务的快速发展、业务复杂度越来越高,几乎每个公司的系统都会从单体走向分布式,特别是转向微服务架构。随之而来就必然遇到分布式事务这个难题。分布式事务是在分布式环境下,遵循CAP理论,在CAP三者中只能够三选二,与本地事务不同,分布式事务ACID的支持情况如下:

  • 原子性:严格遵循
  • 一致性:事务完成后的一致性严格遵循;事务中的一致性可适当放宽
  • 隔离性:并行事务间不可影响;事务中间结果可见性允许安全放宽
  • 持久性:严格遵循

那么分布式事务是那种的组合呢?

1.3.1 强一致性事务方案

  • 基于XA的2PC或者3PC

XA 事务是典型的强一致性事务,也就是完全遵循事务的 ACID 设计原则。XA 协议是由 X/Open 组织提出的分布式事务处理规范,主要定义了事务管理器 TM 和局部资源管理器 RM 之间的接口。目前主流的数据库,比如 oracle、DB2 都是支持 XA 协议的。其中事务管理器 TM通过一个全局事务id(xid)来控制多个局部资源管理器 RM 。基于XA的分布式事务实现方式有One Phase Commit:weak XA、Two Phase Commit:2PC两种形式。其中2PC是XA的标准实现方式。

  • 基于业务层的TCC

TCC模型是把锁的粒度完全交给业务处理,它需要每个子事务业务都实现Try-Confirm/Cancel接口。

1.3.1 弱一致性事务方案

  • 基于消息队列的补偿机制

基于消息队列的一致性方案是通过消息中间件保证上下游应用数据操作的一致性。基本思路是将本地操作和发送消息放在一个事务中,下游应用向消息系统订阅该消息,收到消息后执行相应操作。本质上是依靠消息的重试机制和分布式事务消息,达到最终一致性。消息驱动的缺点是:耦合度高,需要在业务系统中引入MQ(比如Kafka),导致系统复杂度增加。

  • 基于本地消息表的补偿机制

它采用本地事务表记录所有的事务操作SQL,如果子事务提交成功,将会删除事务日志;如果执行失败,则会按照配置的重试次数,尝试再次提交,即最大努力的进行提交,尽量保证数据的一致性,这里可以根据不同的业务场景,平衡C和A,采用同步重试或异步重试。

  • Saga

分布式事务的各种方案实现复杂度较高,各种方案的优缺点和应用场景各不相同,本文结合ShardingSphere和Aurora介绍几种ShardingSphere和Aurora实现的几种方案以帮助大家理清各种方案的应用场景与集成方法。

2.ShardingSphere分布式事务原理分析

2.1 Sharding-JDBC事务实现模型分析

ShardingSphere支持的分布式事务方式有三种 LOCAL、XA、BASE,这三种事务实现方式都是采用的对代码无侵入的方式实现的。

2.2 XA方案

ShardingSphere 在整合 XA 事务时,采用分离 XA 事务管理和连接池管理的方式,做到对应用程序的零侵入。主要支持一下以下功能:

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

其中基于Atomikos的处理流程如下

2.3 BASE方案

如果将实现了 ACID 的事务要素的事务称为刚性事务的话,那么基于 BASE 事务要素的事务则称为柔性事务。 BASE 是基本可用、柔性状态和最终一致性这三个要素的缩写。

  • 基本可用(Basically Available)保证分布式事务参与方不一定同时在线;
  • 柔性状态(Soft state)则允许系统状态更新有一定的延时,这个延时对客户来说不一定能够察觉;
  • 最终一致性(Eventually consistent)通常是通过消息传递的方式保证系统的最终一致性。

在 ACID 事务中对隔离性的要求很高,在事务执行过程中,必须将所有的资源锁定。 柔性事务的理念则是通过业务逻辑将互斥锁操作从资源层面上移至业务层面。 通过放宽对强一致性要求,来换取系统吞吐量的提升。

基于 ACID 的强一致性事务和基于 BASE 的最终一致性事务都不是银弹,只有在最适合的场景中才能发挥它们的最大长处。

使用场景:对于 BASE 事务,提供了分布式环境下,对数据最终一致性的保证。由于在整个事务过程中,不会像 XA 事务那样全程锁定资源,所以性能较好。适用于对并发性能要求很高并且允许出现短暂数据不一致的业务场景。

2.3.1基于Seata方案

整合Seata AT事务时,需要把TM,RM,TC的模型融入到ShardingSphere 分布式事务的SPI的生态中。在数据库资源上,Seata通过对接DataSource接口,让JDBC操作可以同TC进行RPC通信。同样,ShardingSphere也是面向DataSource接口对用户配置的物理DataSource进行了聚合,因此把物理DataSource二次包装为Seata的DataSource后,就可以把Seata AT事务融入到ShardingSphere的分片中。

在Seata模型中,全局事务的上下文存放在线程变量中,通过扩展服务间的transport,可以完成线程变量的传递,分支事务通过线程变量判断是否加入到整个Seata全局事务中。而ShardingSphere的分片执行引擎通常是按多线程执行,因此整合Seata AT事务时,需要扩展主线程和子线程的事务上下文传递,这同服务间的上下文传递思路完全相同。

2.3.2基于Saga方案

ShardingSphere的柔性事务已通过第三方servicecomb-saga组件实现的,通过SPI机制注入使用。ShardingSphere是基于反向SQL技术实现的反向补偿操作,它将对数据库进行更新操作的SQL自动生成反向SQL,并交由Saga-actuator引擎执行。使用方则无需再关注如何实现补偿方法,将柔性事务管理器的应用范畴成功的定位回了事务的本源——数据库层面。

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

实现原理:Saga柔性事务的实现类为SagaShardingTransactionMananger, ShardingSphere通过Hook的方式拦截逻辑SQL的解析和路由结果,这样,在分片物理SQL执行前,可以生成逆向SQL,在事务提交阶段再把SQL调用链交给Saga引擎处理。如下图:

以下是XA和BASE两种分布式事务模式的对比

A B C
1 对比项 ShardingSphere-JDBC-XA ShardingSphere-JDBC-BASE
2 业务改造 需要 seata 或 sage 服务
3 一致性 支持 最终一致
4 隔离性 支持 业务方保证
5 并发性能 严重衰退 略微衰退
6 适合场景 短事务 & 低并发 长事务 & 高并发

3.实现环境搭建

3.1 搭建aurora分布式集群集群

3.2clone代码

https://github.com/liujk1029/shardingsphere-jdbc-sample.git

3.3修改配置文件

修改application-sharding-databases-tables.properties中每个数据源的连接信息

spring.shardingsphere.datasource.ds-0.jdbc-url=jdbc:mysql://xxxx:3306/ds0?serverTimezone=UTC&useSSL=false&useUnicode=true&characterEncoding=UTF-8
spring.shardingsphere.datasource.ds-0.type=com.zaxxer.hikari.HikariDataSourcespring.shardingsphere.datasource.ds-0.driver-class-name=com.mysql.jdbc.Driver
spring.shardingsphere.datasource.ds-0.username=xxxx
spring.shardingsphere.datasource.ds-0.password=xxxx

spring.shardingsphere.datasource.ds-1.jdbc-url=jdbc:mysql://xxxx:3306/ds1?serverTimezone=UTC&useSSL=false&useUnicode=true&characterEncoding=UTF-8
spring.shardingsphere.datasource.ds-1.type=com.zaxxer.hikari.HikariDataSourcespring.shardingsphere.datasource.ds-1.driver-class-name=com.mysql.jdbc.Driver
spring.shardingsphere.datasource.ds-1.username=xxxx
spring.shardingsphere.datasource.ds-1.password=xxxx

spring.shardingsphere.datasource.ds-2.jdbc-url=jdbc:mysql://xxxx:3306/ds2?serverTimezone=UTC&useSSL=false&useUnicode=true&characterEncoding=UTF-8
spring.shardingsphere.datasource.ds-2.type=com.zaxxer.hikari.HikariDataSource
spring.shardingsphere.datasource.ds-2.driver-class-name=com.mysql.jdbc.Driver
spring.shardingsphere.datasource.ds-2.username=xxxx
spring.shardingsphere.datasource.ds-2.password=xxxx

4. 集成Aurora数据库实现分布式事务

注意:spring事务回滚机制,在以下情况下事务才会回滚,默认情况,spring事务只在发生未被捕获的 RuntimeExcetpion类型异常时才回滚,如果您在代码使用try-catch捕获了异常,那么也不会回滚,另外您如果下午在指定的异常情况下也会,可以通过@Transactional(rollbackFor = MyException.class)指定回滚的异常类型。

4.1 基于XA的Amazon Aurora Mysql分布式事务实现

4.1.1架构概览

基于XA模式的分布式事务,不需要其他的外部依赖,可以直接使用ShardingSphere-JDBC jar包进行实现,能快速的集成到java应用程序当中,让应用程序快速支持分布式事务。同时对于Aurora Mysql来讲,也不会有任何改造,每个集群只需要各自维护好各自集群的数据可用性就可以,整体架构的耦合性很低,职责明确。

4.1.2实现逻辑

核心依赖项:

      <!-- 使用 XA 事务时,需要引入此模块 -->
        <dependency>
            <groupId>org.apache.shardingsphere</groupId>
            <artifactId>shardingsphere-transaction-xa-core</artifactId>
            <version>5.0.0</version>
        </dependency>

应用程序配置:

# 数据源命名
spring.shardingsphere.datasource.names=ds-0,ds-1,ds-2
# 数据源1的连接信息
spring.shardingsphere.datasource.ds-0.jdbc-url=jdbc:mysql://xxxx.cluster-cconbgqninkj.us-east-1.rds.amazonaws.com:3306/ds0?serverTimezone=UTC&useSSL=false&useUnicode=true&characterEncoding=UTF-8
spring.shardingsphere.datasource.ds-0.type=com.zaxxer.hikari.HikariDataSource
spring.shardingsphere.datasource.ds-0.driver-class-name=com.mysql.jdbc.Driver
spring.shardingsphere.datasource.ds-0.username=xxxx
spring.shardingsphere.datasource.ds-0.password=xxxx
# 数据源2的连接信息
spring.shardingsphere.datasource.ds-1.jdbc-url=jdbc:mysql://xxxx.cluster-cconbgqninkj.us-east-1.rds.amazonaws.com:3306/ds1?serverTimezone=UTC&useSSL=false&useUnicode=true&characterEncoding=UTF-8
spring.shardingsphere.datasource.ds-1.type=com.zaxxer.hikari.HikariDataSource
spring.shardingsphere.datasource.ds-1.driver-class-name=com.mysql.jdbc.Driver
spring.shardingsphere.datasource.ds-1.username=xxxx
spring.shardingsphere.datasource.ds-1.password=xxxx
# 数据源3的连接信息
spring.shardingsphere.datasource.ds-2.jdbc-url=jdbc:mysql://xxxx.cluster-cconbgqninkj.us-east-1.rds.amazonaws.com:3306/ds2?serverTimezone=UTC&useSSL=false&useUnicode=true&characterEncoding=UTF-8
spring.shardingsphere.datasource.ds-2.type=com.zaxxer.hikari.HikariDataSource
spring.shardingsphere.datasource.ds-2.driver-class-name=com.mysql.jdbc.Driver
spring.shardingsphere.datasource.ds-2.username=xxxx
spring.shardingsphere.datasource.ds-2.password=xxxx
# 数据分库的策略
spring.shardingsphere.rules.sharding.default-database-strategy.standard.sharding-column=user_id
spring.shardingsphere.rules.sharding.default-database-strategy.standard.sharding-algorithm-name=database-inline
spring.shardingsphere.rules.sharding.sharding-algorithms.database-inline.type=INLINE
spring.shardingsphere.rules.sharding.sharding-algorithms.database-inline.props.algorithm-expression=ds-$->{user_id % 3}
# 数据分表策略
spring.shardingsphere.rules.sharding.tables.t_order.actual-data-nodes=ds-$->{0..2}.t_order_$->{0..2}
spring.shardingsphere.rules.sharding.tables.t_order.table-strategy.standard.sharding-column=order_id
spring.shardingsphere.rules.sharding.tables.t_order.table-strategy.standard.sharding-algorithm-name=t-order-inline
spring.shardingsphere.rules.sharding.sharding-algorithms.t-order-inline.type=INLINE
spring.shardingsphere.rules.sharding.sharding-algorithms.t-order-inline.props.algorithm-expression=t_order_$->{order_id % 3}
# 主键生成方式和算法
spring.shardingsphere.rules.sharding.tables.t_order.key-generate-strategy.column=order_id
spring.shardingsphere.rules.sharding.tables.t_order.key-generate-strategy.key-generator-name=snowflake
spring.shardingsphere.rules.sharding.key-generators.snowflake.type=SNOWFLAKE

关键代码

@Transactional
@ShardingSphereTransactionType(TransactionType.XA)
public void insert() {
    jdbcTemplate.execute("INSERT INTO t_order (user_id, status) VALUES (?, ?)",
                (PreparedStatementCallback<TransactionType>) preparedStatement -> {
            doInsert(20, preparedStatement);
            return TransactionTypeHolder.get();
        });
}

4.1.3测试验证

该测试程序将会五个接口,分别是创建表、删除表、批量成功插入、批量失败插入、统计表行数。

在配置好应用程序和环境后,启动该服务。

查看三个数据库的表信息:

此时三个数据库的表都为空,调用创建表接口

curl --location --request GET 'http://xxxx:8088/shardingsphere-2pc-xa-app/create-table'
create table success

查看数据库创建结果

此时批量成功向数据库插入20条数据

curl --location --request GET 'http://xxxx:8088/shardingsphere-2pc-xa-app/insert'
insert success

查看目前数据库表中总的数量

curl --location --request GET 'http://xxxx:8088/shardingsphere-2pc-xa-app/count'
20

查看数据库数据分布,可以看到总共20条数据,已经按照我们设置的分库编表的固执,分布到不同数据库的不同表里面,并且数据分布的规则也是按照我们预期的规则,同时批量插入的事务也已经成功提交,此时XA分布式事务提交验证成功。

接下来,我们清理数据库,开始验证数据库分布式事务失败的场景。

清理完成数据库各个表之后,可以看到数据库表都是空的。

接下来执行批量失败插入操作,这个操作里面,会先插入20条数据到各个数据库的各个表中,然后再后面抛出一个异常,验证数据是否按照预期正常回滚。

/**
  * 批量插入失败
  */
@Transactional
@ShardingSphereTransactionType(TransactionType.XA)
public void insertFailed() {
        jdbcTemplate.execute("INSERT INTO t_order (user_id, status) VALUES (?, ?)", (PreparedStatementCallback<TransactionType>) preparedStatement -> {
            doInsert(20, preparedStatement);
            throw new SQLException("mock transaction failed");
        });
}

执行批量失败插入操作

curl --location --request GET 'http://xxxx:8088/shardingsphere-2pc-xa-app/insert-failed'
insert fail

此时查看数据库验证记录数量是否为0

curl --location --request GET 'http://xxxx:8088/shardingsphere-2pc-xa-app/count'
0

验证数据库中是否存在数据

通过验证,我们可以看到,Aurora Mysql与Shardingsphere-JDBC集成使用,可以支持XA模式的两阶段分布式事务。

4.2.基于BASE Seata  的 Amazon Aurora Mysql的分布式事务实现

4.2.1架构概览

基于BASE柔性分布式事务的架构,需要依赖外部服务来实现。目前主流的实现方案是依赖Seata Server进行实现。由于在整个事务过程中,不会像 XA 事务那样全程锁定资源,所以性能较好。适用于对并发性能要求很高并且允许出现短暂数据不一致的业务场景。

4.2.2实现逻辑

核心依赖项:

<!-- 使用 BASE 事务时,需要引入此模块 -->
        <dependency>
            <groupId>org.apache.shardingsphere</groupId>
            <artifactId>shardingsphere-transaction-base-seata-at</artifactId>
            <version>5.0.0</version>
        </dependency>
        <dependency>
            <groupId>io.seata</groupId>
            <artifactId>seata-all</artifactId>
            <version>1.5.2</version>
            <exclusions>
                <exclusion>
                    <groupId>org.springframework</groupId>
                    <artifactId>spring-context</artifactId>
                </exclusion>
                <exclusion>
                    <groupId>org.springframework</groupId>
                    <artifactId>spring-core</artifactId>
                </exclusion>
                <exclusion>
                    <groupId>org.springframework</groupId>
                    <artifactId>spring-beans</artifactId>
                </exclusion>
                <exclusion>
                    <groupId>org.springframework</groupId>
                    <artifactId>spring-aop</artifactId>
                </exclusion>
                <exclusion>
                    <groupId>org.springframework</groupId>
                    <artifactId>spring-webmvc</artifactId>
                </exclusion>
            </exclusions>
        </dependency>

应用程序配置:

# 数据源命名
spring.shardingsphere.datasource.names=ds-0,ds-1,ds-2
# 数据源1的连接信息
spring.shardingsphere.datasource.ds-0.jdbc-url=jdbc:mysql://xxxx.cluster-cconbgqninkj.us-east-1.rds.amazonaws.com:3306/ds0?serverTimezone=UTC&useSSL=false&useUnicode=true&characterEncoding=UTF-8
spring.shardingsphere.datasource.ds-0.type=com.zaxxer.hikari.HikariDataSource
spring.shardingsphere.datasource.ds-0.driver-class-name=com.mysql.jdbc.Driver
spring.shardingsphere.datasource.ds-0.username=xxxx
spring.shardingsphere.datasource.ds-0.password=xxxx
# 数据源2的连接信息
spring.shardingsphere.datasource.ds-1.jdbc-url=jdbc:mysql://xxxx.cluster-cconbgqninkj.us-east-1.rds.amazonaws.com:3306/ds1?serverTimezone=UTC&useSSL=false&useUnicode=true&characterEncoding=UTF-8
spring.shardingsphere.datasource.ds-1.type=com.zaxxer.hikari.HikariDataSource
spring.shardingsphere.datasource.ds-1.driver-class-name=com.mysql.jdbc.Driver
spring.shardingsphere.datasource.ds-1.username=xxxx
spring.shardingsphere.datasource.ds-1.password=xxxx
# 数据源3的连接信息
spring.shardingsphere.datasource.ds-2.jdbc-url=jdbc:mysql://xxxx.cluster-cconbgqninkj.us-east-1.rds.amazonaws.com:3306/ds2?serverTimezone=UTC&useSSL=false&useUnicode=true&characterEncoding=UTF-8
spring.shardingsphere.datasource.ds-2.type=com.zaxxer.hikari.HikariDataSource
spring.shardingsphere.datasource.ds-2.driver-class-name=com.mysql.jdbc.Driver
spring.shardingsphere.datasource.ds-2.username=xxxx
spring.shardingsphere.datasource.ds-2.password=xxxx
# 数据分库的策略
spring.shardingsphere.rules.sharding.default-database-strategy.standard.sharding-column=user_id
spring.shardingsphere.rules.sharding.default-database-strategy.standard.sharding-algorithm-name=database-inline
spring.shardingsphere.rules.sharding.sharding-algorithms.database-inline.type=INLINE
spring.shardingsphere.rules.sharding.sharding-algorithms.database-inline.props.algorithm-expression=ds-$->{user_id % 3}
# 数据分表策略
spring.shardingsphere.rules.sharding.tables.t_order.actual-data-nodes=ds-$->{0..2}.t_order_$->{0..2}
spring.shardingsphere.rules.sharding.tables.t_order.table-strategy.standard.sharding-column=order_id
spring.shardingsphere.rules.sharding.tables.t_order.table-strategy.standard.sharding-algorithm-name=t-order-inline
spring.shardingsphere.rules.sharding.sharding-algorithms.t-order-inline.type=INLINE
spring.shardingsphere.rules.sharding.sharding-algorithms.t-order-inline.props.algorithm-expression=t_order_$->{order_id % 3}
# 主键生成方式和算法
spring.shardingsphere.rules.sharding.tables.t_order.key-generate-strategy.column=order_id
spring.shardingsphere.rules.sharding.tables.t_order.key-generate-strategy.key-generator-name=snowflake
spring.shardingsphere.rules.sharding.key-generators.snowflake.type=SNOWFLAKE

关键代码

@Transactional
@ShardingSphereTransactionType(TransactionType.BASE)
public void insert() {
     jdbcTemplate.execute("INSERT INTO t_order (user_id, status) VALUES (?, ?)",
                (PreparedStatementCallback<TransactionType>) preparedStatement -> {
            doInsert(20, preparedStatement);
            return TransactionTypeHolder.get();
        });
}

seata-server 连接配置

transport {
  # tcp udt unix-domain-socket
  type = "TCP"
  #NIO NATIVE
  server = "NIO"
  #enable heartbeat
  heartbeat = true
  #thread factory for netty
  thread-factory {
    boss-thread-prefix = "NettyBoss"
    worker-thread-prefix = "NettyServerNIOWorker"
    server-executor-thread-prefix = "NettyServerBizHandler"
    share-boss-worker = false
    client-selector-thread-prefix = "NettyClientSelector"
    client-selector-thread-size = 1
    client-worker-thread-prefix = "NettyClientWorkerThread"
    # netty boss thread size,will not be used for UDT
    boss-thread-size = 1
    #auto default pin or 8
    worker-thread-size = 8
  }
}
service {
  #vgroup->rgroup
  vgroupMapping.my_test_tx_group = "default"
  #only support single node
  default.grouplist = "127.0.0.1:8091"
  #degrade current not support
  enableDegrade = false
  #disable
  disable = false
}
client {
  async.commit.buffer.limit = 10000
  lock {
    retry.internal = 10
    retry.times = 30
  }
}

https://github.com/seata/seata/releases下载seata-server服务器软件包,将其解压缩,并启动该服务。

Usage: sh seata-server.sh(for linux and mac) or cmd seata-server.bat(for windows) [options]
  Options:
    --host, -h
      The address is expose to registration center and other service can access seata-server via this ip
      Default: 0.0.0.0
    --port, -p
      The port to listen.
      Default: 8091
    --storeMode, -m
      log store mode : file、db
      Default: file
    --help
e.g.
sh seata-server.sh -p 8091 -h 127.0.0.1 -m file

4.2.3测试验证

该测试程序将会五个接口,分别是创建表、删除表、批量成功插入、批量失败插入、统计表行数,同时需要单独启动seata-server来支持柔性分布式事务。在配置好应用程序和环境后,启动该服务。

使用BASE柔性分布式事务和使用XA模式两阶段提交分布式事务的测试验证方式相同,都是先创建数据库和表,然后验证批量写入成功的测试用例,最后验证批量写入失败的测试用例。

最终可以得到结论,Aurora Mysql与Shardingsphere-JDBC集成使用,可以支持BASE模式柔性分布式事务,通过最终一致性,可以给应用程序带来更好的吞吐能力。

5.总结

本篇文章通过Aurora Mysql 与 ShardingSphere-JDBC的集成使用,拓展了Aurora的能力边界,使得Aurora在分库分表的场景下,可以方便的支持分布式事务,同时可以根据业务场景的需要,选择不同的分布式事务模式,为业务发展提供价值。同时,ShardingSphere-JDBC作为应用程序访问数据的中间层,可以与Java当下主流的spring-boot快速集成,让开发者可以快速上手云上分库分表的分布式事务处理方案,而无需对于java应用程序进行大量修改。另外ShardingSphere在整个云上分库分表方案中,使用较为广泛,具有较高的参考价值,建议云上开发者在技术方案选型的时候,可以重点参考。

6.参考资料

分布式事务

https://juejin.cn/post/6844903896851169287

ShardingSphere文档

https://shardingsphere.apache.org/document/current/en/overview/

https://juejin.cn/post/6992742055051001863

ShardingSphere分布式事务参考资料

https://shardingsphere.apache.org/blog/en/material/realization/

Seata参考资料

https://seata.io/zh-cn/blog/seata-quick-start.html

https://seata.io/zh-cn/blog/seata-at-tcc-saga.html

本篇作者

刘倞坤

亚马逊云科技解决方案架构师,目前主要负责对于使用AWS云计算资源客户的解决方案咨询和架构设计,帮助客户实现上云和云迁移的具体方案。曾就职于蚂蚁金服、平安、腾讯云,对于系统架构、系统研发、数据库等方向有深入从业经验。

孙进华

亚马逊云科技资深解决方案架构师,负责帮助客户进行上云架构的设计和咨询。加入AWS前自主创业负责电商平台搭建和车企电商平台整体架构设计。曾就职于全球领先的通讯设备公司,担任高级工程师,负责LTE设备系统的多个子系统的开发与架构设计。在高并发、高可用系统架构设计、微服务架构设计、数据库、中间件、IOT等方面有着丰富的经验。

叶小微

亚马逊云科技解决方案架构师, 曾就职于IBM, 后从事电商相关和企业数字化转型工作, 拥有多年架构设计、研发、项目管理经验。在工作流、微服务、系统集成等方向有丰富的解决实际问题的经验。