让您轻松入门分布式事务Seata和分库分表sharding-sphere的整合

Posted 请叫我东子

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了让您轻松入门分布式事务Seata和分库分表sharding-sphere的整合相关的知识,希望对你有一定的参考价值。

1.介绍

本篇将介绍,如何进行seata1.2.0、sharding-sphere4.1.0和dubbo2.7.5 的整合,以及使用nacos作为我们的配置中心和注册中心。如果你还是一个初学者,先建议学习一下,陈建斌的七步带你集成Seata 1.2 高可用搭建,这篇文章清楚的阐述了初学者容易遇到的5个问题,并且都提供完整的解决思路。

2.环境配置

  • mysql: 5.7.12

  • nacos: 1.2.1

  • spring-boot: 2.2.6.RELEASE

  • seata: 1.2.0

  • dubbo:2.7.5

  • sharding-sphere: 4.1.0

  • 开发环境: jdk1.8.0

2.1 nacos安装

nacos下载:https://github.com/alibaba/nacos/releases/tag/1.2.1

Nacos 快速入门:https://nacos.io/en-us/docs/quick-start.html

sh startup.sh -m standalone

在浏览器打开Nacos web 控制台:http://127.0.0.1:8848/nacos/index.html

输入nacos的账号和密码 分别为nacos:nacos


这是时候naocs 就正常启动了。

2.2 seata1.2.0安装

2.2.1 在 Seata Release 下载最新版的 Seata Server 并解压得到如下目录:
.
├──bin
├──conf
└──lib
2.2.2 修改 conf/registry.conf 配置,

目前seata支持如下的file、nacos 、apollo、zk、consul的注册中心和配置中心。这里我们以nacos 为例。
将 type 改为 nacos

registry 
  # file 、nacos 、eureka、redis、zk、consul、etcd3、sofa
  type = "nacos"

  nacos 
    application = "seata-server"
    serverAddr = "127.0.0.1:8848"
    namespace = "40508bb4-179e-4c98-a2f1-c2c031c20b3c"
    cluster = "default"
    username = "worker2"
    password = "xxxxxxx"
  


config 
  # file、nacos 、apollo、zk、consul、etcd3
  type = "nacos"

  nacos 
    serverAddr = "127.0.0.1:8848"
    namespace = "40508bb4-179e-4c98-a2f1-c2c031c20b3c"
    group = "SEATA_GROUP"
    username = "worker2"
    password = "xxxxxxx"
  

  • serverAddr = “127.0.0.1:8848” :nacos 的地址
  • namespace = “” :nacos的命名空间默认为``
  • cluster = “default” :集群设置未默认 default
2.2.3 修改 conf/config.txt配置
service.vgroupMapping.order-service-seata-service-group=default
service.vgroupMapping.account-service-seata-service-group=default
service.vgroupMapping.storage-service-seata-service-group=default
service.vgroupMapping.business-service-seata-service-group=default
store.mode=db
store.db.driverClassName=com.mysql.jdbc.Driver
store.db.datasource=druid
store.db.dbType=mysql
store.db.url=jdbc:mysql://127.0.0.1:3306/seata?useUnicode=true
store.db.user=root
store.db.password=123456
store.db.minConn=1
store.db.maxConn=3
store.db.global.table=global_table
store.db.branch.table=branch_table
store.db.query-limit=100
store.db.lockTable=lock_table

配置的详细说明参考官网:https://seata.io/zh-cn/docs/user/configurations.html

这里主要修改了如下几项:

  • store.mode :存储模式 默认file 这里我修改为db 模式 ,并且需要三个表global_tablebranch_tablelock_table
  • store.db.driverClassName: 0.8.0版本默认没有,会报错。添加了 com.mysql.jdbc.Driver
  • store.db.datasource=dbcp :数据源 dbcp
  • store.db.db-type=mysql : 存储数据库的类型为mysql
  • store.db.url=jdbc:mysql://127.0.0.1:3306/seata?useUnicode=true : 修改为自己的数据库urlport数据库名称
  • store.db.user=root :数据库的账号
  • store.db.password=123456:数据库的密码
  • service.vgroupMapping.order-service-seata-service-group=default
  • service.vgroupMapping.account-service-seata-service-group=default
  • service.vgroupMapping.storage-service-seata-service-group=default
  • service.vgroupMapping.business-service-seata-service-group=default
2.2.4 db模式下的所需的三个表

数据库脚本位于https://github.com/seata/seata/tree/develop/script/server/db

这里我用的是mysql数据库,直接下载mysq.sql就可以了。

global_table的表结构

CREATE TABLE `global_table` (
  `xid` varchar(128) NOT NULL,
  `transaction_id` bigint(20) DEFAULT NULL,
  `status` tinyint(4) NOT NULL,
  `application_id` varchar(64) DEFAULT NULL,
  `transaction_service_group` varchar(64) DEFAULT NULL,
  `transaction_name` varchar(64) DEFAULT NULL,
  `timeout` int(11) DEFAULT NULL,
  `begin_time` bigint(20) DEFAULT NULL,
  `application_data` varchar(2000) DEFAULT NULL,
  `gmt_create` datetime DEFAULT NULL,
  `gmt_modified` datetime DEFAULT NULL,
  PRIMARY KEY (`xid`),
  KEY `idx_gmt_modified_status` (`gmt_modified`,`status`),
  KEY `idx_transaction_id` (`transaction_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;

branch_table的表结构

CREATE TABLE `branch_table` (
  `branch_id` bigint(20) NOT NULL,
  `xid` varchar(128) NOT NULL,
  `transaction_id` bigint(20) DEFAULT NULL,
  `resource_group_id` varchar(32) DEFAULT NULL,
  `resource_id` varchar(256) DEFAULT NULL,
  `lock_key` varchar(128) DEFAULT NULL,
  `branch_type` varchar(8) DEFAULT NULL,
  `status` tinyint(4) DEFAULT NULL,
  `client_id` varchar(64) DEFAULT NULL,
  `application_data` varchar(2000) DEFAULT NULL,
  `gmt_create` datetime DEFAULT NULL,
  `gmt_modified` datetime DEFAULT NULL,
  PRIMARY KEY (`branch_id`),
  KEY `idx_xid` (`xid`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;


lock_table的表结构

create table `lock_table` (
  `row_key` varchar(128) not null,
  `xid` varchar(96),
  `transaction_id` long ,
  `branch_id` long,
  `resource_id` varchar(256) ,
  `table_name` varchar(32) ,
  `pk` varchar(32) ,
  `gmt_create` datetime ,
  `gmt_modified` datetime,
  primary key(`row_key`)
);
2.2.5 将 Seata 配置添加到 Nacos 中

nacos导入脚本位于https://github.com/seata/seata/tree/develop/script/config-center/nacos

使用方法:

sh $SEATAPATH/script/config-center/nacos/nacos-config.sh -h localhost -p 8848 -g SEATA_GROUP -t 40508bb4-179e-4c98-a2f1-c2c031c20b3c -u worker-w xxxxxx

参数描述:

  • -h: host, 默认值 localhost.

  • -p: port, 默认值 is 8848.

  • -g: 配置分组 默认值 ‘SEATA_GROUP’.

  • -t: 命名空间.

  • -u: 用户名, nacos 1.2.0+ 之后添加权限验证 默认为“”

  • -w: 密码, nacos 1.2.0+ 之后添加权限验证 默认为“”

在 Nacos 管理页面应该可以看到Group 为SEATA_GROUP的配置

这样seata-sever就搭建完成。

3.sharding-sphere中seata柔性事务实现

3.1 实现原理

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

3.2实现原理图

3.3 实现的步骤

  1. Init(Seata引擎初始化)
    包含Seata柔性事务的应用启动时,用户配置的数据源会按seata.conf的配置,适配为Seata事务所需的DataSourceProxy,并且注册到RM中。

  2. Begin(开启Seata全局事务)
    TM控制全局事务的边界,TM通过向TC发送Begin指令,获取全局事务ID,所有分支事务通过此全局事务ID,参与到全局事务中;全局事务ID的上下文存放在当前线程变量中。

  3. 执行分片物理SQL
    处于Seata全局事务中的分片SQL通过RM生成undo快照,并且发送participate指令到TC,加入到全局事务中。ShardingSphere的分片物理SQL是按多线程方式执行,因此整合Seata AT事务时,需要在主线程和子线程间进行全局事务ID的上下文传递,这同服务间的上下文传递思路完全相同。

  4. Commit/rollback(提交Seata事务)
    提交Seata事务时,TM会向TC发送全局事务的commit和rollback指令,TC根据全局事务ID协调所有分支事务进行commit和rollback。

4.sharding-sphere中seata的整合

4.1使用Spring-boot引入Maven依赖
<dependency>
    <groupId>org.apache.shardingsphere</groupId>
    <artifactId>sharding-jdbc-spring-boot-starter</artifactId>
    <version>$shardingsphere.version</version>
</dependency>

<!-- 使用BASE事务时,需要引入此模块 -->
<dependency>
    <groupId>org.apache.shardingsphere</groupId>
    <artifactId>sharding-transaction-base-seata-at</artifactId>
    <version>$sharding-sphere.version</version>
</dependency>
4.2.Seata的AT模式使用的BASE柔性事务管理器

在每一个分片数据库实例中执创建undo_log表(以MySQL为例)

CREATE TABLE IF NOT EXISTS `undo_log`
(
  `id`            BIGINT(20)   NOT NULL AUTO_INCREMENT COMMENT 'increment id',
  `branch_id`     BIGINT(20)   NOT NULL COMMENT 'branch transaction id',
  `xid`           VARCHAR(100) NOT NULL COMMENT 'global transaction id',
  `context`       VARCHAR(128) NOT NULL COMMENT 'undo_log context,such as serialization',
  `rollback_info` LONGBLOB     NOT NULL COMMENT 'rollback info',
  `log_status`    INT(11)      NOT NULL COMMENT '0:normal status,1:defense status',
  `log_created`   DATETIME     NOT NULL COMMENT 'create datetime',
  `log_modified`  DATETIME     NOT NULL COMMENT 'modify datetime',
  PRIMARY KEY (`id`),
  UNIQUE KEY `ux_undo_log` (`xid`, `branch_id`)
) ENGINE = InnoDB
  AUTO_INCREMENT = 1
  DEFAULT CHARSET = utf8 COMMENT ='AT transaction mode undo table';
4.3.在classpath中增加seata.conf
client 
    application.id = example    ## 应用唯一id
    transaction.service.group = my_test_tx_group   ## 所属事务组

4.4业务方发起全局事务,配置柔性事务类型
 @GlobalTransactional(timeoutMills = 300000, name = "dubbo-gts-seata-example")
 @Override
public ObjectResponse handleBusiness(BusinessDTO businessDTO) 
        TransactionTypeHolder.set(TransactionType.BASE);
        //执行业务逻辑

备注:也可是使用注解@ShardingTransactionType的形式

 @GlobalTransactional(timeoutMills = 300000, name = "dubbo-gts-seata-example")
 @ShardingTransactionType(TransactionType.BASE)
@Override
 public ObjectResponse handleBusiness(BusinessDTO businessDTO) 
     //执行业务逻辑  

        

5.案例实现

参考官网中用户购买商品的业务逻辑。整个业务逻辑由4个微服务提供支持:

  • 库存服务:扣除给定商品的存储数量。
  • 订单服务:根据购买请求创建订单。
  • 帐户服务:借记用户帐户的余额。
  • 业务服务:处理业务逻辑。

请求逻辑架构

5.1 源码地址

https://github.com/lidong1665/seata-spring-boot-dubbo-nacos-shardingsphere-examples

  • samples-common :公共模块

  • samples-account :用户账号模块

  • samples-order :订单模块

  • samples-storage :库存模块

  • samples-business :业务模块

5.2 数据库

注意: MySQL必须使用InnoDB engine.

如下,并且每个库中都需要一个undo_log表

5.3 以账号服务为例

分析需要项目中所需要的配置

5.3.1 引入的依赖
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.2.6.RELEASE</version>
        <relativePath/> <!-- lookup parent from repository -->
    </parent>
    <artifactId>seata-spring-boot-dubbo-nacos-shardingsphere-examples</artifactId>
    <packaging>pom</packaging>
    <name>seata-spring-boot-dubbo-nacos-shardingsphere-examples</name>
    <groupId>io.seata</groupId>
    <version>1.2.0</version>
    <description>Demo project for Spring Boot Dubbo</description>

    <modules>
        <module>samples-common-service</module>
        <module>samples-account-service</module>
        <module>samples-order-service</module>
        <module>samples-storage-service</module>
        <module>samples-business-service</module>
    </modules>

    <properties>
        <springboot.verison>2.2.6.RELEASE</springboot.verison>
        <java.version>1.8</java.version>
        <mybatis-plus.version>2.3</mybatis-plus.version>
        <nacos.version>0.2.3</nacos.version>
        <lombok.version>1.16.22</lombok.version>
        <dubbo.version>2.7.5</dubbo.version>
        <nacos-client.verison>1.2.1</nacos-client.verison>
        <seata.version>1.2.0</seata.version>
        <netty.version>4.1.32.Final</netty.version>
        <sharding-sphere.version>4.1.0</sharding-sphere.version>
    </properties>

    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
            <version>$springboot.verison</version>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter</artifactId>
            <version>$springboot.verison</version>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <version>$springboot.verison</version>
        </dependency>

        <dependency>
            <groupId>com.baomidou</groupId>
            <artifactId>mybatis-plus-boot-starter</artifactId>
            <version>3.3.1</version>
        </dependency>


        <dependency>
            <groupId>org.apache.dubbo</groupId>
            <artifactId>dubbo</artifactId>
            <version>$dubbo.version</version>
            <exclusions>
                <exclusion>
                    <artifactId>spring</artifactId>
                    <groupId>org.springframework</groupId>
                </exclusion>
            </exclusions>
        </dependency>
        <dependency>
            <groupId>org.apache.dubbo</groupId>
            <artifactId>dubbo-spring-boot-starter</artifactId>
            <version>$dubbo.version</version>
        </dependency>

        <!-- https://mvnrepository.com/artifact/org.apache.dubbo/dubbo-config-spring -->
        <dependency>
            <groupId>org.apache.dubbo</groupId>
            <artifactId>dubbo-configcenter-nacos</artifactId>
            <version>$dubbo.version</version>
        </dependency>
        <dependency>
            <groupId>org.apache.dubbo</groupId>
            <artifactId>dubbo-registry-nacos</artifactId>
            <version>$dubbo.version</version>
        </dependency>
        <dependency>
            <groupId>org.apache.dubbo</groupId>
            <artifactId>dubbo-metadata-report-nacos</artifactId>
            <version>$dubbo.version</version>
        </dependency>

        <!-- https://mvnrepository.com/artifact/io.seata/seata-all -->

        <dependency>
            <groupId>io.seata</groupId>
            <artifactId>seata-spring-boot-starter</artifactId>
            <versionShardingShpere分库分表5-ShardingSphere分布式事务详解

微服务分库分表分布式事务管理APM链路跟踪性能分析演示项目

linux中MyCat(分库分表)入门安装

数据库分库分表,分片配置轻松入门!

ShardingJdbc-分表;分库分表;读写分离;一主多从+分表;一主多从+分库分表;公共表;数据脱敏;分布式事务

数据量大了一定要分表,分库分表Sharding-JDBC入门与项目实战