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

1abca104950a7150d43062493cc55c6a.gif

1、前言

 #01 

Amazon Aurora 介绍

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

Aurora 的最大数据存储量现在支持多达 128TB,而且可以支持存储的动态收缩。计算方面,Aurora 提供多个读副本的可扩展性配置,支持一个区域内多达15个读副本的扩展,提供多主的架构来支持同一个区域内4个写节点的扩展、 Serverless 无服务器化的架构实例级别的秒级纵向扩展和全球数据库来实现数据库的低延迟跨区域扩展。

随着用户数据量的增长,Aurora 已经提供了很好的扩展性,那是否可以进一步增强更多的数据量、更多的并发访问能力呢?您可以考虑利用分库分表的方式来支持底层多个 Aurora 集群的配置。基于此,包含这篇博客在内的系列博客会进行相应的介绍,旨在为您进行分库分表时代理或者 JDBC 的选择提供参考。

 #02 

ShardingSphere 介绍

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

693e5ac5d2dfe636b0e955de4c0139f9.png

Sharding-JDBC 特点

● 它使用客户端直连数据库,以 jar 包形式提供服务;

● 无需额外部署和依赖,可理解为增强版的 JDBC 驱动,完全兼容 JDBC 和各种 ORM 框架;

● 适用于任何基于 JDBC 的 ORM 框架,如:JPA、Hibernate、Mybatis 或直接使用 JDBC;

● 支持任何第三方的数据库连接池,如:DBCP、C3P0、BoneCP、HikariCP 等;

● 支持任意实现 JDBC 规范的数据库,目前支持 MySQL、PostgreSQL,Oracle,SQLServer 以及任何可使用 JDBC 访问的数据库;

● 采用无中心化架构,与应用程序共享资源,适用于 Java 开发的高性能的轻量级 OLTP 应用。

Sharding-JDBC 与应用集成的架构

3a09cf4516ea912737f9e596a53b6726.png

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 分片,则此两张表互为绑定表关系,绑定表之间的多表关联查询不会出现笛卡尔积关联,关联查询效率将大大提升;

● 广播表:指所有的分片数据源中都存在的表,表结构和表中的数据在每个数据库中均完全一致,适用于数据量不大且需要与海量数据的表进行关联查询的场景,例如:字典表、配置表。

 #03 

分布式事务介绍

传统单体应用场景下,系统的数据保存在一个数据库实例中,通常场景的关系数据库都能自动提供事务保证,并且这种情况下的事务称为本地事务,能保证原子性、一致性、隔离性、持久性(ACID 特性)。

随着业务的快速发展、业务复杂度越来越高,几乎每个公司的系统都会从单体走向分布式,特别是转向微服务架构。随之而来就必然遇到分布式事务这个难题。分布式事务是在分布式环境下,遵循 CAP 理论,在 CAP 三者中只能够三选二,与本地事务不同,分布式事务 ACID 的支持情况如下:

● 原子性:严格遵循

● 一致性:事务完成后的一致性严格遵循;事务中的一致性可适当放宽

● 隔离性:并行事务间不可影响;事务中间结果可见性允许安全放宽

● 持久性:严格遵循

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

强一致性事务方案

● 基于 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 接口。

弱一致性事务方案

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

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

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

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

● Saga

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

2、ShardingSphere  分布式

事务原理分析

 #01 

Sharding-JDBC 事务实现模型分析

c47de6d6a2083313ad464893290eb76c.png

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

b4129a3c8608652a6eefbfa385815a58.png

 #02 

XA 方案

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

支持数据分片后的跨库 XA 事务;

● 两阶段提交保证操作的原子性和数据的强一致性;

● 服务宕机重启后,提交/回滚中的事务可自动恢复;

● SPI 机制整合主流的 XA 事务管理器,默认  Atomikos;

同时支持 XA 和非 XA 的连接池。

e3f5094192c29096575b52c8e80af574.png

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

11cd49c8974dbeaa820f9e7312db95bf.png

 #03 

BASE 方案

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

● 基本可用(Basically Available)保证分布式事务参与方不一定同时在线;

● 柔性状态(Soft state)则允许系统状态更新有一定的延时,这个延时对客户来说不一定能够察觉;

● 最终一致性(Eventually consistent)通常是通过消息传递的方式保证系统的最终一致性。

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

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

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

基于 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 事务时,需要扩展主线程和子线程的事务上下文传递,这同服务间的上下文传递思路完全相同。

04e9107a100ffe4c7ff13ae8d06945aa.png

基于 Saga 方案

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

● 完全支持跨库事务;

● 支持失败 SQL 重试及最大努力送达;

● 支持反向 SQL、自动生成更新快照以及自动补偿;

● 默认使用关系型数据库进行快照及事务日志的持久化,支持使用 SPI 的方式加载其他类型的持久化。

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

550c7b340aeda5f04d80d2478db64cae.png

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

66a70c81c2ed8aa7a263abf079d93457.png

3、实现环境搭建

 #01 

搭建 aurora 分布式集群集群

8c38865f56a58b246832b9103ac5cd98.png

 #02 

clone 代码

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

左滑查看更多

 #03 

修改配置文件

修改 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) 指定回滚的异常类型。

 #01 

基于 XA 的 Amazon Aurora MySQL

分布式事务实现

架构概览

c06d921595ad0d7135f0daf88229351b.png

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

实现逻辑

核心依赖项:

<!-- 使用 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();
        });
}

左滑查看更多

测试验证

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

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

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

101b1324d07b466b9ebb649ef6a7b84d.png

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

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

左滑查看更多

查看数据库创建结果

e7bfd0794f08cb3cf0b575c8ee1e957a.png

此时批量成功向数据库插入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 分布式事务提交验证成功。

f8d0acdcde8f99839325be28dced40ce.png

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

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

f5d4c73d3e388c1ef567cfd98ef99fae.png

接下来执行批量失败插入操作,这个操作里面,会先插入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

左滑查看更多

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

e5e724fcf028907ec744f522ac5fdc35.png

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

 #02 

基于 BASE Seata  的 Amazon

Aurora MySQL 的分布式事务实现

架构概览

ac031fdafa86677e1c7820127f14374a.png

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

实现逻辑

核心依赖项:

<!-- 使用 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

左滑查看更多

测试验证

该测试程序将会五个接口,分别是创建表、删除表、批量成功插入、批量失败插入、统计表行数,同时需要单独启动 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

本篇作者

e3fe51652cd02d39c4b32da96a8324f7.jpeg

刘倞坤

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

bc2f800c8f7750fabb4dbaa43b0317be.jpeg

孙进华

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

d81f2c571d639b9d4ba5b426b6402a99.jpeg

叶小微

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

67c20068ae35a6e974f1c49ac9685f35.gif

17e76d6d9904d3e7be39a807c3c802e8.gif

听说,点完下面4个按钮

就不会碰到bug了!

e626f06a6732aa646db0a54bf1ecaf21.gif

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值