当前位置: 首页 > news >正文

spring cloud seata集成

目录

一、seata使用场景 

二、seata组成

三、seata服务端搭建

四、客户端使用seata

4.1 客户端增加undo_log表

4.2 客户端增加seata相关配置

4.3 客户端使用注解

五、测试


一、seata使用场景 

微服务中,一个业务涉及到多个微服务系统,每个微服务系统连接不同的数据库,要求数据一致性时使用。如下订单操作,调用下订单方法后,需要增加订单记录、减少产品库存;订单记录和产品库存 调用不同的微服务  数据存储在不同的数据库中;

调用下订单方法时,订单服务或库存服务任何一个出现问题,此方法执行失败,数据库记录需回滚。

理论支持:cap、base;

理论依据:二阶段提交法(准备、执行);三阶段提交法(询问、准备、执行);消息最终一致性;最大努力通知法;

解决方案:tcc(try-confirm-cancel)、sega、X/A等。

二、seata组成

seata是spring cloud生态中的分布式事务解决方案,包括seata服务端和客户端;

seata服务端是独立部署的;(seata担当事务协调器角色)

seata客户端,即每个微服务增加相关依赖和配置,使用@GlobalTransactional(rollbackFor = Exception.class)注解即可;

三、seata服务端搭建

1. 下载seata服务端包;

本文使用的是seata1.7.0版本的包。

2. 修改seata配置文件 application.yml,使用nacos注册seata服务,管理seata服务配置;

路径seata>conf,application.yml

#  Copyright 1999-2019 Seata.io Group.
#
#  Licensed under the Apache License, Version 2.0 (the "License");
#  you may not use this file except in compliance with the License.
#  You may obtain a copy of the License at
#
#  http://www.apache.org/licenses/LICENSE-2.0
#
#  Unless required by applicable law or agreed to in writing, software
#  distributed under the License is distributed on an "AS IS" BASIS,
#  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
#  See the License for the specific language governing permissions and
#  limitations under the License.server:port: 7091spring:application:name: seata-serverlogging:config: classpath:logback-spring.xmlfile:path: ${user.home}/logs/seataextend:logstash-appender:destination: 127.0.0.1:4560kafka-appender:bootstrap-servers: 127.0.0.1:9092topic: logback_to_logstash
console:user:username: seatapassword: seataseata:config:# support: nacos 、 consul 、 apollo 、 zk  、 etcd3type: nacosnacos:server-addr: 127.0.0.1:8948namespace:group: SEATA_GROUPusername: nacospassword: context-path:##if use MSE Nacos with auth, mutex with username/password attribute#access-key:#secret-key:data-id: seataServer.propertiesregistry:# support: nacos 、 eureka 、 redis 、 zk  、 consul 、 etcd3 、 sofatype: nacosnacos:application: seata-serverserver-addr: 127.0.0.1:8948group: SEATA_GROUPnamespace:cluster: defaultusername: nacospassword: context-path:##if use MSE Nacos with auth, mutex with username/password attribute#access-key:#secret-key:security:secretKey: tokenValidityInMilliseconds: 1800000ignore:urls: /,/**/*.css,/**/*.js,/**/*.html,/**/*.map,/**/*.svg,/**/*.png,/**/*.jpeg,/**/*.ico,/api/v1/auth/login

在nacos中增加seata配置:

seataServer.properties配置文件:

#For details about configuration items, see https://seata.io/zh-cn/docs/user/configurations.html
#Transport configuration, for client and server
transport.type=TCP
transport.server=NIO
transport.heartbeat=true
transport.enableTmClientBatchSendRequest=false
transport.enableRmClientBatchSendRequest=true
transport.enableTcServerBatchSendResponse=false
transport.rpcRmRequestTimeout=30000
transport.rpcTmRequestTimeout=30000
transport.rpcTcRequestTimeout=30000
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
transport.serialization=seata
transport.compressor=none#Transaction routing rules configuration, only for the client
service.vgroupMapping.default_tx_group=default
#If you use a registry, you can ignore it
service.default.grouplist=127.0.0.1:8091
service.enableDegrade=false
service.disableGlobalTransaction=false#Transaction rule configuration, only for the client
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=true
client.rm.tableMetaCheckerInterval=60000
client.rm.sqlParserType=druid
client.rm.reportSuccessEnable=false
client.rm.sagaBranchRegisterEnable=false
client.rm.sagaJsonParser=fastjson
client.rm.tccActionInterceptorOrder=-2147482648
client.tm.commitRetryCount=5
client.tm.rollbackRetryCount=5
client.tm.defaultGlobalTransactionTimeout=60000
client.tm.degradeCheck=false
client.tm.degradeCheckAllowTimes=10
client.tm.degradeCheckPeriod=2000
client.tm.interceptorOrder=-2147482648
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.undo.compress.enable=true
client.undo.compress.type=zip
client.undo.compress.threshold=64k
#For TCC transaction mode
tcc.fence.logTableName=tcc_fence_log
tcc.fence.cleanPeriod=1h#Log rule configuration, for client and server
log.exceptionRate=100#Transaction storage configuration, only for the server. The file, db, and redis configuration values are optional.
store.mode=db
store.lock.mode=db
store.session.mode=db
#Used for password encryption
store.publicKey=#These configurations are required if the `store mode` is `db`. If `store.mode,store.lock.mode,store.session.mode` are not equal to `db`, you can remove the configuration block.
store.db.datasource=druid
store.db.dbType=mysql
store.db.driverClassName=com.mysql.cj.jdbc.Driver
store.db.url=jdbc:mysql://127.0.0.1:3306/seata?useUnicode=true&rewriteBatchedStatements=true
store.db.user=root
store.db.password=
store.db.minConn=5
store.db.maxConn=30
store.db.globalTable=global_table
store.db.branchTable=branch_table
store.db.distributedLockTable=distributed_lock
store.db.queryLimit=100
store.db.lockTable=lock_table
store.db.maxWait=5000#Transaction rule configuration, only for the server
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
server.distributedLockExpireTime=10000
server.xaerNotaRetryTimeout=60000
server.session.branchAsyncQueueSize=5000
server.session.enableBranchAsyncRemove=false
server.enableParallelRequestHandle=false#Metrics configuration, only for the server
metrics.enabled=false
metrics.registryType=compact
metrics.exporterList=prometheus
metrics.exporterPrometheusPort=9898

3. 创建seata服务所需数据库表;

在seata script目录下找到sql脚本

执行sql语句建表:

-- -------------------------------- 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_status_gmt_modified` (`status` , `gmt_modified`),KEY `idx_transaction_id` (`transaction_id`)
) ENGINE = InnoDBDEFAULT CHARSET = utf8mb4;-- 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 = InnoDBDEFAULT CHARSET = utf8mb4;-- the table to store lock data
CREATE TABLE IF NOT EXISTS `lock_table`
(`row_key`        VARCHAR(128) NOT NULL,`xid`            VARCHAR(128),`transaction_id` BIGINT,`branch_id`      BIGINT       NOT NULL,`resource_id`    VARCHAR(256),`table_name`     VARCHAR(32),`pk`             VARCHAR(36),`status`         TINYINT      NOT NULL DEFAULT '0' COMMENT '0:locked ,1:rollbacking',`gmt_create`     DATETIME,`gmt_modified`   DATETIME,PRIMARY KEY (`row_key`),KEY `idx_status` (`status`),KEY `idx_branch_id` (`branch_id`),KEY `idx_xid` (`xid`)
) ENGINE = InnoDBDEFAULT CHARSET = utf8mb4;CREATE TABLE IF NOT EXISTS `distributed_lock`
(`lock_key`       CHAR(20) NOT NULL,`lock_value`     VARCHAR(20) NOT NULL,`expire`         BIGINT,primary key (`lock_key`)
) ENGINE = InnoDBDEFAULT CHARSET = utf8mb4;INSERT INTO `distributed_lock` (lock_key, lock_value, expire) VALUES ('AsyncCommitting', ' ', 0);
INSERT INTO `distributed_lock` (lock_key, lock_value, expire) VALUES ('RetryCommitting', ' ', 0);
INSERT INTO `distributed_lock` (lock_key, lock_value, expire) VALUES ('RetryRollbacking', ' ', 0);
INSERT INTO `distributed_lock` (lock_key, lock_value, expire) VALUES ('TxTimeoutCheck', ' ', 0);

四、客户端使用seata

示例由三个服务组成,seataDemoWeb、demo-order、demo-product;

其中seataDemoWeb服务提供rest接口test,此接口调用demo-order和demo-product服务,增加订单记录,修改库存。

4.1 客户端增加undo_log表

demo-order和demo-product,两个服务对应的数据库均需增加undo_log表;

建表语句:

CREATE TABLE `undo_log` (`id` bigint(20) NOT NULL AUTO_INCREMENT,`branch_id` bigint(20) NOT NULL,`xid` varchar(100) NOT NULL,`context` varchar(128) NOT NULL,`rollback_info` longblob NOT NULL,`log_status` int(11) NOT NULL,`log_created` datetime NOT NULL,`log_modified` datetime NOT NULL,`ext` varchar(100) DEFAULT NULL,PRIMARY KEY (`id`),UNIQUE KEY `ux_undo_log` (`xid`,`branch_id`)
) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8;

4.2 客户端增加seata相关配置

seataDemoWeb、demo-order和demo-product在application.properties中增加seata配置

seata.enabled=true
seata.application-id=${spring.application.name}
seata.tx-service-group=seata-tx-group
seata.service.vgroup-mapping.seata-tx-group=default
seata.registry.type=nacos
seata.registry.nacos.server-addr=127.0.0.1:8948
seata.registry.nacos.username=nacos
seata.registry.nacos.password=
seata.registry.nacos.namespace=public
seata.registry.nacos.group=SEATA_GROUP
seata.registry.nacos.application=seata-server

pom增加seata依赖,完整pom.xml

<?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 https://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.10.RELEASE</version><relativePath/> <!-- lookup parent from repository --></parent><groupId>hj.example</groupId><artifactId>productDemo</artifactId><version>1.0.0</version><packaging>jar</packaging><properties><lombok.version>1.18.24</lombok.version></properties><dependencies><dependency><groupId>hj.example</groupId><artifactId>demoCommon</artifactId><version>1.0.0</version></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter</artifactId></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId></dependency><dependency><groupId>mysql</groupId><artifactId>mysql-connector-java</artifactId><version>8.0.12</version></dependency><dependency><groupId>org.projectlombok</groupId><artifactId>lombok</artifactId><version>${lombok.version}</version></dependency><!-- nacos --><dependency><groupId>com.alibaba.cloud</groupId><artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId><version>2.2.5.RELEASE</version></dependency><dependency><groupId>com.alibaba.cloud</groupId><artifactId>spring-cloud-starter-alibaba-nacos-config</artifactId><version>2.2.5.RELEASE</version></dependency><dependency><groupId>com.alibaba.cloud</groupId><artifactId>spring-cloud-starter-dubbo</artifactId><version>2.2.5.RELEASE</version></dependency><!-- seata --><dependency><groupId>com.alibaba.cloud</groupId><artifactId>spring-cloud-starter-alibaba-seata</artifactId><version>2.2.5.RELEASE</version><exclusions><exclusion><groupId>io.seata</groupId><artifactId>seata-spring-boot-starter</artifactId></exclusion></exclusions></dependency><dependency><groupId>io.seata</groupId><artifactId>seata-spring-boot-starter</artifactId><version>1.7.0</version></dependency></dependencies>
</project>

 

4.3 客户端使用注解

在seataDemoWeb服务中,增加@GlobalTransaction注解

package hj.example.seatademoweb.controller;import com.baomidou.mybatisplus.extension.service.IService;
import hj.example.democommon.entity.DemoOrder;
import hj.example.democommon.entity.DemoProduct;
import hj.example.democommon.entity.StateEnum;
import hj.example.democommon.services.DemoOrderService;
import hj.example.democommon.services.DemoProductService;
import io.seata.spring.annotation.GlobalTransactional;
import org.apache.dubbo.config.annotation.DubboReference;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;import java.util.Random;/*** @Description: TODO* @Author: * @Date: 2023/8/29**/
@RestController
public class TestController {@DubboReference(interfaceName = "demoOrderService")private DemoOrderService demoOrderService;@DubboReference(interfaceName = "demoProductService")private DemoProductService demoProductService;@RequestMapping("/test")@GlobalTransactional(rollbackFor = Exception.class)public ResponseEntity<Object> test() {DemoOrder demoOrder =new DemoOrder();demoOrder.setAccountId("1");demoOrder.setState(StateEnum.NEW.name());demoOrderService.save(demoOrder);DemoProduct demoProduct = new DemoProduct();demoProduct.setNum(Math.random()*10000);demoProductService.save(demoProduct);return new ResponseEntity<>("success", HttpStatus.OK);}
}

五、测试

修改4.3中的代码,debug查看回滚

DemoProduct demoProduct = new DemoProduct();
demoProduct.setNum(1/0);
demoProductService.save(demoProduct);

http://www.lryc.cn/news/149039.html

相关文章:

  • HTTP 常⻅的状态码有哪些,以及适⽤场景
  • 后端给前端传参数忽略空属性
  • SPSS教程:如何绘制带误差的折线图
  • 积分商城小程序如何精细化运营
  • 企业网络日志管理:EventLog Analyzer的卓越之处
  • Python算法——滑动窗口问题
  • 使用 MATLAB 和 Simulink 对雷达系统进行建模和仿真
  • Linux 中的 sysctl 命令及示例
  • Mybatis批量更新数据及其优化
  • 包含文心一言在内的首批国产大模型 全面开放
  • Linux运维工程师面试题集锦
  • 深度学习——感受野以及与图像修复的问题
  • 微服务容错 Resilience4j 接口服务-容错原理
  • OceanBase 4.x改装:另一种全链路追踪的尝试
  • springCloudAlibaba详解
  • python通过docker打包执行
  • 实现公网远程访问:Windows本地快速搭建SFTP文件服务器并配置端口映射
  • 获取文件路径
  • 如何自己实现一个丝滑的流程图绘制工具(八) 创建节点的文本标签
  • Spring Boot多数据源配置运行报错:No operations allowed after connection closed连接异常的解决
  • 3、QT 的基础控件的使用
  • 爬虫逆向实战(二十六)--某某学堂登录
  • leetcode分类刷题:哈希表(Hash Table)(四、前缀和 处理连续子数组)
  • 如何处理生产环境中的数据倾斜问题?
  • 【WSN无线传感器网络恶意节点】使用 MATLAB 进行无线传感器网络部署研究
  • C# 实现浏览器控件设置
  • 1130 - Host ‘17216.18083‘ is not allowed to connect to this MySQL server
  • 使用Spring的getBeansOfType实现接口多实现类的动态调用
  • (笔记三)opencv图像基础操作
  • PHP入门及环境搭建 - XAMPP