SpringCloud 集成 Seata Nacos+db实现高可用的集群模式

目录

一、Seata+Mysql+Nacos进行部署

1、修改Seata的配置文件

2、创建数据库

3、修改registry.conf

4、nacos中添加配置文件

5、集群部署

二、分布式事务Seata的使用案例

1、分布式事务的问题引出

2、Seata实现分布式事务的案例

三、分布式的解决方案的理解


对应多进程的分布式系统来说,本地事务已不能保证数据集的一致性,由此我们可以使用Seata分布式事务来解决。

一、Seata+Mysql+Nacos进行部署

Docker安装Seata见我的这篇博客:Docker 部署微服务架构的各项环境_Dragon Wu的博客-CSDN博客_基于docker的微服务架构

本次案例基于Linux环境Seata1.3.0+Mysql8来实现

由于分布式架构需要支持集群高可用所以这里需要用到mysql。

这里我们将seata对于版本的script文件夹放入对应的目录中,便于后续使用:

seata/script at v1.3.0 · seata/seata · GitHub

1、修改Seata的配置文件

进入Seata的目file.conf

修改配置如下:数据库要求必须为5.7以上版本。

 

2、创建数据库

数据要求5.7以上版本

 运行对应版本的脚本:

seata/script/server/db at v1.3.0 · seata/seata · GitHub

-- -------------------------------- The script used when storeMode is 'db' --------------------------------
-- the table to store GlobalSession data
CREATE TABLE IF NOT EXISTS `global_table`
(
    `xid`                       VARCHAR(128) NOT NULL,
    `transaction_id`            BIGINT,
    `status`                    TINYINT      NOT NULL,
    `application_id`            VARCHAR(32),
    `transaction_service_group` VARCHAR(32),
    `transaction_name`          VARCHAR(128),
    `timeout`                   INT,
    `begin_time`                BIGINT,
    `application_data`          VARCHAR(2000),
    `gmt_create`                DATETIME,
    `gmt_modified`              DATETIME,
    PRIMARY KEY (`xid`),
    KEY `idx_gmt_modified_status` (`gmt_modified`, `status`),
    KEY `idx_transaction_id` (`transaction_id`)
) ENGINE = InnoDB
  DEFAULT CHARSET = utf8;

-- the table to store BranchSession data
CREATE TABLE IF NOT EXISTS `branch_table`
(
    `branch_id`         BIGINT       NOT NULL,
    `xid`               VARCHAR(128) NOT NULL,
    `transaction_id`    BIGINT,
    `resource_group_id` VARCHAR(32),
    `resource_id`       VARCHAR(256),
    `branch_type`       VARCHAR(8),
    `status`            TINYINT,
    `client_id`         VARCHAR(64),
    `application_data`  VARCHAR(2000),
    `gmt_create`        DATETIME(6),
    `gmt_modified`      DATETIME(6),
    PRIMARY KEY (`branch_id`),
    KEY `idx_xid` (`xid`)
) ENGINE = InnoDB
  DEFAULT CHARSET = utf8;

-- the table to store lock data
CREATE TABLE IF NOT EXISTS `lock_table`
(
    `row_key`        VARCHAR(128) NOT NULL,
    `xid`            VARCHAR(96),
    `transaction_id` BIGINT,
    `branch_id`      BIGINT       NOT NULL,
    `resource_id`    VARCHAR(256),
    `table_name`     VARCHAR(32),
    `pk`             VARCHAR(36),
    `gmt_create`     DATETIME,
    `gmt_modified`   DATETIME,
    PRIMARY KEY (`row_key`),
    KEY `idx_branch_id` (`branch_id`)
) ENGINE = InnoDB
  DEFAULT CHARSET = utf8;

3、修改registry.conf

 注册中心改为nacos

修改nacos的配置

 修改配置中心

 

4、nacos中添加配置文件

修改script里的config.txt文件

修改为文件如下:使用db后,这里还需修改数据库的配置

如需一定机房容错可配置多个:

这里不赘述,需要使用时可以去查阅。

transport.type=TCP
transport.server=NIO
transport.heartbeat=true
transport.enableClientBatchSendRequest=false
transport.threadFactory.bossThreadPrefix=NettyBoss
transport.threadFactory.workerThreadPrefix=NettyServerNIOWorker
transport.threadFactory.serverExecutorThreadPrefix=NettyServerBizHandler
transport.threadFactory.shareBossWorker=false
transport.threadFactory.clientSelectorThreadPrefix=NettyClientSelector
transport.threadFactory.clientSelectorThreadSize=1
transport.threadFactory.clientWorkerThreadPrefix=NettyClientWorkerThread
transport.threadFactory.bossThreadSize=1
transport.threadFactory.workerThreadSize=default
transport.shutdown.wait=3
service.vgroupMapping.chengdu=default
service.default.grouplist=127.0.0.1:8091
service.enableDegrade=false
service.disableGlobalTransaction=false
client.rm.asyncCommitBufferLimit=10000
client.rm.lock.retryInterval=10
client.rm.lock.retryTimes=30
client.rm.lock.retryPolicyBranchRollbackOnConflict=true
client.rm.reportRetryCount=5
client.rm.tableMetaCheckEnable=false
client.rm.sqlParserType=druid
client.rm.reportSuccessEnable=false
client.rm.sagaBranchRegisterEnable=false
client.tm.commitRetryCount=5
client.tm.rollbackRetryCount=5
client.tm.degradeCheck=false
client.tm.degradeCheckAllowTimes=10
client.tm.degradeCheckPeriod=2000
store.mode=db
store.db.datasource=druid
store.db.dbType=mysql
store.db.driverClassName=com.mysql.jdbc.Driver
store.db.url=jdbc:mysql://127.0.0.1:3308/seata_server?useUnicode=true
store.db.user=username
store.db.password=password
store.db.minConn=5
store.db.maxConn=30
store.db.globalTable=global_table
store.db.branchTable=branch_table
store.db.queryLimit=100
store.db.lockTable=lock_table
store.db.maxWait=5000
store.redis.host=127.0.0.1
store.redis.port=6379
store.redis.maxConn=10
store.redis.minConn=1
store.redis.database=0
store.redis.password=null
store.redis.queryLimit=100
server.recovery.committingRetryPeriod=1000
server.recovery.asynCommittingRetryPeriod=1000
server.recovery.rollbackingRetryPeriod=1000
server.recovery.timeoutRetryPeriod=1000
server.maxCommitRetryTimeout=-1
server.maxRollbackRetryTimeout=-1
server.rollbackRetryTimeoutUnlockEnable=false
client.undo.dataValidation=true
client.undo.logSerialization=jackson
client.undo.onlyCareUpdateColumns=true
server.undo.logSaveDays=7
server.undo.logDeletePeriod=86400000
client.undo.logTable=undo_log
client.log.exceptionRate=100
transport.serialization=seata
transport.compressor=none
metrics.enabled=false
metrics.registryType=compact
metrics.exporterList=prometheus
metrics.exporterPrometheusPort=9898

修改好配置,启动对应的nacos,进入script下的nacos目录,运行脚本后将会添加到nacos中

 默认是本地nacos地址

也可指定命令:

sh nacos-config.sh -h 127.0.0.1 -p 8848

运行截图:

 运行成功后再观察Nacos可以看到多了很多的配置文件。

5、集群部署

可参考以下参数多次启动不同端口的seata部署即可实现集群部署。

最后在nacos服务中便可看到多个seata实例了。

可以看到seata-server已运行成功:

二、分布式事务Seata的使用案例

1、分布式事务的问题引出

为了得出分布式事务所参数的问题,我模拟了以下案例进行探索。

首先,我开启了Seata服务和消费者服务、生产者服务个一台,分别注册到Nacos中:

 研究思路:我通过order-service服务去调用stock-serivce服务,这两个服务均开启了@Transational本地事务看看,在本地事务的情况下,是否能保证分布式事务安全。

测试方法如下:通过order-serivce的一个接口调用后修改order表的name字段并且随之调用stock-service来对stock表的num字段进行减一的操作。

 测试核心部分如下:

 这里通过openFeign来远程调用stock-service的该接口:

 使用ApiPost对order-serivce的该接口进行请求:

可以看到由于我设置的异常,使程序发生回滚,这时查看数据库看效果:

 

 问题很显然了,@Transactional本地事务不能支持分布式事务的解决。

2、Seata实现分布式事务的案例

以下为AT默认模式下的案例

(1)添加核心依赖

<!--分布式事务seata的依赖-->
        <dependency>
            <groupId>com.alibaba.cloud</groupId>
            <artifactId>spring-cloud-starter-alibaba-seata</artifactId>
        </dependency>

(2)各微服务对应数据库中添加undo_log表

SET NAMES utf8mb4;
SET FOREIGN_KEY_CHECKS = 0;

-- ----------------------------
-- Table structure for undo_log
-- ----------------------------
DROP TABLE IF EXISTS `undo_log`;
CREATE TABLE `undo_log`  (
  `branch_id` bigint(20) NOT NULL COMMENT '分支事务ID',
  `xid` varchar(100) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL COMMENT '全局事务ID',
  `context` varchar(128) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL COMMENT '上下文',
  `rollback_info` longblob NOT NULL COMMENT '回滚信息',
  `log_status` int(11) NOT NULL COMMENT '状态,0正常,1全局已完成',
  `log_created` datetime(6) NOT NULL COMMENT '创建时间',
  `log_modified` datetime(6) NOT NULL COMMENT '修改时间',
  UNIQUE INDEX `ux_undo_log`(`xid`, `branch_id`) USING BTREE
) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci COMMENT = 'AT transaction mode undo table' ROW_FORMAT = Compact;

SET FOREIGN_KEY_CHECKS = 1;

undo_log表用于做回滚的日志记录表

(3)每个微服务里添加配置如下

配置事务分组:

spring:
  cloud:
    alibaba:
      seata:
        tx-service-group: chengdu

service.vgroupMapping.chengdu=default

这里的名字为之前config.txt配置文件中你自定义的名字:

service.vgroupMapping.你自定义的名字=default

(4)每个微服务添加配置

seata:
  registry:
    type: nacos
    nacos:
      server-addr: my-server:8848   # seata server 所在的nacos服务地址
      application: seata-server  #seata server 的服务名seata-server,如果没有修改可以不配
      username: nacos
      password: XXX
      group: SEATA_GROUP #seata server 所在的组,默认就是SEATA_GROUP,没有改也可以
  config:
    type: nacos
    nacos:
      server-addr: my-server:8848
      username: nacos
      password: xxx
      group: SEATA_GROUP

(5)将@Transactional本地事务替换为@GlobalTransactional注解进行分布式事务调用

(6)测试

现在再来进行之前的报错测试

 ApiPost进行请求后再查看数据库:

 可以看到此时两个数据库都进行了回滚:

 分布式事务使用成功!

三、分布式的解决方案的理解

来看看专家怎么说:SEATA是什么?它的四种分布式事务模式

  • 2
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 3
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值