分布式事务Seata-AT模式

1. seata安装

  1. docker 安装
docker run --name seata-server \-p 8091:8091 \-p 7091:7091 \-e SEATA_IP=192.168.0.250 \-e SEATA_PORT=8091 \seataio/seata-server
  1. 将安装好的配置文件数据,拷贝一份到物理机
docker cp seata-serve:/seata-server/resources /User/seata/config
  1. 修改配置文件
server:port: 7091spring:application:name: seata-serverlogging:config: classpath:logback-spring.xmlfile:path: ${log.home:${user.home}/logs/seata}extend:logstash-appender:destination: 127.0.0.1:4560kafka-appender:bootstrap-servers: 127.0.0.1:9092topic: logback_to_logstashconsole:user:username: seatapassword: seata
seata:config:# support: nacos, consul, apollo, zk, etcd3type: nacosnacos:server-addr: 192.168.0.250:8848namespace:group: SEATA_GROUPusername: nacospassword: nacoscontext-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: 192.168.0.250:8848group: SEATA_GROUPnamespace:cluster: defaultusername: nacospassword: nacoscontext-path:store:# support: file 、 db 、 redismode: dbdb:datasource: druiddb-type: mysqldriver-class-name: com.mysql.jdbc.Driverurl: jdbc:mysql://192.168.0.250:3306/seata-work?rewriteBatchedStatements=true # 配置数据库服务端地址,提前初始化SQLuser: rootpassword: mysql_xMYB44min-conn: 10max-conn: 100global-table: global_tablebranch-table: branch_tablelock-table: lock_tabledistributed-lock-table: distributed_lockquery-limit: 1000max-wait: 5000security:secretKey: SeataSecretKey0c382ef121d778043159209298fd40bf3850a017tokenValidityInMilliseconds: 1800000ignore:urls: /,/**/*.css,/**/*.js,/**/*.html,/**/*.map,/**/*.svg,/**/*.png,/**/*.jpeg,/**/*.ico,/api/v1/auth/login
  1. 删除旧的seata-server,重新安装,并进行路径映射
docker run --name seata-server \-p 8091:8091 \-p 7091:7091 \-e SEATA_IP=192.168.0.250 \-e SEATA_PORT=8091 \-v /User/seata/config:/seata-server/resources  \seataio/seata-server

2. 数据库初始化

  1. 客户端
-- 注意此处0.3.0+ 增加唯一索引 ux_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;
  1. 服务端
-- -------------------------------- 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);

3. Pom配置

        <dependency><groupId>com.alibaba.cloud</groupId><artifactId>spring-cloud-starter-alibaba-seata</artifactId><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.1</version>  </dependency>

4. seata配置

# 配置seata
seata:enabled: truetx-service-group: xiaoqiu_tx_group # 事务组service:vgroup-mapping:xiaoqiu_tx_group: SEATA_GROUP # 事务组映射grouplist:SEATA_GROUP: 192.168.0.250:8091 # seata ip地址config:nacos:server-addr: 192.168.0.250:8848username: nacospassword: nacosregistry:nacos:server-addr: 192.168.0.250:8848username: nacospassword: nacos

5. 自动回滚

直接把原有的@Transactional替换成@GlobalTransactional即可

1. 当**本机发生异常,且未被全局异常处理器捕获时**,即可直接回滚;
2. 当**外部调用发生异常时,返回的状态码非200**,也可以直接回滚。

6. 手动回滚

  1. 外部异常,但返回状态码还是200

    调用外部接口时,外部接口自己捕获了异常,此时返回的http状态码为200,不会自动回滚,需要根据返回的数据单独判断,并进行手动回滚。

    举例:

    // 初始化简历
    R<Void> r = workResumeServiceFeign.init(user.getId());
    // 如果调用状态不是200,则手动回滚全局事务
    if (r.getStatus() != HttpStatusEnum.SUCCESS.getCode()) {String xid = RootContext.getXID();if (StringUtils.isNotBlank(xid)) {try {GlobalTransactionContext.reload(xid).rollback();} catch (TransactionException e) {log.error("createUsers, 回滚全局事务失败! mobile: {}", mobile, e);} finally {GraceException.display(ResponseStatusEnum.USER_REGISTER_ERROR);}}
    }
    
  2. 本地异常,但异常被全局异常捕获

    此时本地发生了异常,但是由于优雅处理异常的全局异常处理类,把异常吃掉了,所以需要单独处理。此时可以加一个AOP切面,对方法进行包装,手动的拦截要全局事务包裹的类,然后手动回滚异常。

    举例:

    异常代码:

    		@GlobalTransactional@Overridepublic Users createUsers(String mobile) {Users user = getDefaultUsers(mobile);user.setMobile(mobile);usersMapper.insert(user);// 初始化简历workResumeServiceFeign.init(user.getId());// 模拟除0异常int a = 1 / 0;return user;}
    

    切面:

    @Slf4j
    @Component
    @Aspect
    public class SeataTransactionAspect {/*** 调用service之前,手动加入或者创建全局事务*/@Before("execution(* com.xiaoqiu.service.impl.UsersServiceImpl.createUsers(..))")public void beginTransaction(JoinPoint joinPoint) throws TransactionException {log.info("手动开启全局事务");// 手动开启全局事务GlobalTransaction gt = GlobalTransactionContext.getCurrentOrCreate();gt.begin();}/*** 捕获异常,则手动回滚全局事务*/@AfterThrowing(throwing = "throwable",pointcut = "execution(* com.xiaoqiu.service.impl.UsersServiceImpl.createUsers(..))")public void seataRollback(Throwable throwable) throws Throwable {log.warn("捕获到异常信息,则回滚,异常信息为:{}", throwable.getMessage());// 从当前线程获得xidString xid = RootContext.getXID();if (StringUtils.isNotBlank(xid)) {GlobalTransactionContext.reload(xid).rollback();}}
    }
    

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/460893.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Vue生成名片二维码带logo并支持下载

一、需求 生成一张名片&#xff0c;名片上有用户信息以及二维码&#xff0c;名片支持下载功能&#xff08;背景样式可更换&#xff0c;忽略本文章样图样式&#xff09;。 二、参考文章 这不是我自己找官网自己摸索出来的&#xff0c;是借鉴各位前辈的&#xff0c;学以致用&am…

如何利用网站进行仿牌运营?

对于很多人来说&#xff0c;仿牌网站的运营是一项充满挑战的任务&#xff0c;很多初学者对如何开始感到困惑&#xff0c;甚至不清楚仿牌网站的运作机制。此外&#xff0c;搜索引擎对新网站的审核期也使得许多站长倍感压力。那么&#xff0c;如何才能在这一过程中有效地进行SEO优…

数字IC开发:布局布线

数字IC开发&#xff1a;布局布线 前端经过DFT&#xff0c;综合后输出网表文件给后端&#xff0c;由后端通过布局布线&#xff0c;将网表转换为GDSII文件&#xff1b;网表文件只包含单元器件及其连接等信息&#xff0c;GDS文件则包含其物理位置&#xff0c;具体的走线&#xff1…

传智杯 第六届-复赛-C

题目描述&#xff1a; 小红有一个数组&#xff0c;她每次可以选择数组的一个元素 xxx &#xff0c;将这个元素分成两个元素 aaa 和 bbb &#xff0c;使得 abxabxabx。请问小红最少需要操作多少次才可以使得数组的所有元素都相等。 输入描述: 第一行输入一个整数 n(1≤n≤10^5)…

华为配置 之 GVRP协议

目录 简介&#xff1a; 配置GVRP&#xff1a; 总结&#xff1a; 简介&#xff1a; GVRP&#xff08;GARP VLAN Registration Protocol&#xff09;&#xff0c;称为VLAN注册协议&#xff0c;是用来维护交换机中的VLAN动态注册信息&#xff0c;并传播该信息到其他交换机中&…

外包干了7天,技术明显退步。。。。。

先说一下自己的情况&#xff0c;本科生&#xff0c;22年通过校招进入南京某软件公司&#xff0c;干了接近2年的功能测试&#xff0c;今年年初&#xff0c;感觉自己不能够在这样下去了&#xff0c;长时间呆在一个舒适的环境会让一个人堕落!而我已经在一个企业干了2年的功能测试&…

openGauss开源数据库实战十

文章目录 任务十 openGauss逻辑结构:数据库管理任务目标实施步骤一、登录到openGauss二、创建数据库三、查看数据库集群中有哪些数据库四、查看数据库默认表空间的信息五、查看数据库下有哪些模式六、查看数据库下有哪些表七、修改数据库的默认表空间八、重命名数据库九、删除数…

H3C OSPF配置

OSPF配置实验 实验拓扑图 实验需求 1.配置IP地址 2.分区域配置OSPF&#xff0c;实现全网互通 3.为了路由结构稳定&#xff0c;要求路由器使用环回口作为Router-id&#xff0c;ABR的环回口宣告进骨干区域 实验配置 1.配置IP地址 R1&#xff1a; <H3C>system-view …

飞桨首创 FlashMask :加速大模型灵活注意力掩码计算,长序列训练的利器

在 Transformer 类大模型训练任务中&#xff0c;注意力掩码&#xff08;Attention Mask&#xff09;一方面带来了大量的冗余计算&#xff0c;另一方面因其 O ( N 2 ) O(N^2) O(N2)巨大的存储占用导致难以实现长序列场景的高效训练&#xff08;其中 N N N为序列长度&#xff09;…

乘云而上,OceanBase再越山峰

一座山峰都是一个挑战&#xff0c;每一次攀登都是一次超越。 商业数据库时代&#xff0c;面对国外数据库巨头这座大山&#xff0c;实现市场突破一直都是中国数据库产业多年夙愿&#xff0c;而OceanBase在金融核心系统等领域的攻坚克难&#xff0c;为产业突破交出一副令人信服的…

为什么要使用Golang以及如何入门

什么是golang&#xff1f; Go是一种开放源代码的编程语言&#xff0c;于2009年首次发布&#xff0c;由Google的Rob Pike&#xff0c;Robert Griesemer和Ken Thompson开发。基于C的语法&#xff0c;它进行了一些更改和改进&#xff0c;以安全地管理内存使用&#xff0c;管理对象…

《文心一言插件设计与开发》赛题三等奖方案 | NoteTable

一年一度的 CCF大数据与计算智能大赛&#xff08;简称2024 CCF BDCI大赛&#xff09;又开始啦~~ 程序员们可冲一波嗷~ 大赛地址&#xff1a;http://go.datafountain.cn/6506 现在我们再次释放往届获奖方案&#xff0c; 为新一届大赛的同学们提供一些方案和灵感参考~ 大家借鉴借…

el-dialog支持全局拖拽功能

1.首先在全局的组件实现拖拽功能&#xff0c;结构如下 dialogDrag.vue的内容 <script>export default {mounted() {// 获取当前的dialog及其headerlet aimDialog this.$el.getElementsByClassName(el-dialog)[0];let aimHeader this.$el.getElementsByClassName(el-d…

XCode16中c++头文件找不到解决办法

XCode16中新建Framework&#xff0c;写完自己的c代码后&#xff0c;提示“<string> file not found”等诸如此类找不到c头文件的错误。 工程结构如下&#xff1a; App是测试应用&#xff0c;BoostMath是Framework。基本结构可以参考官方demo&#xff1a;Mix Swift and …

开源代码管理平台Gitlab如何本地化部署并实现公网环境远程访问私有仓库

文章目录 前言1. 下载Gitlab2. 安装Gitlab3. 启动Gitlab4. 安装cpolar5. 创建隧道配置访问地址6. 固定GitLab访问地址6.1 保留二级子域名6.2 配置二级子域名 7. 测试访问二级子域名 前言 本文主要介绍如何在Linux CentOS8 中搭建GitLab私有仓库并且结合内网穿透工具实现在公网…

JavaEE初阶---网络原理(四)--IP协议/DNS协议

文章目录 1.初识网络层&#xff08;了解即可&#xff09;2.地址管理2.1动态分配2.2网络地址转换2.3IP-v6最终解 3.网段划分4.以太网协议--数据链路层5.DNS应用层协议 1.初识网络层&#xff08;了解即可&#xff09; 网络层做的事情就是下面的两个&#xff1a; 1&#xff09;地…

4.2-6 使用Hadoop WebUI

文章目录 1. 查看HDFS集群状态1.1 端口号说明1.2 用主机名访问1.3 主节点状态1.4 用IP地址访问1.5 查看数据节点 2. 操作HDFS文件系统2.1 查看HDFS文件系统2.2 在HDFS上创建目录2.3 上传文件到HDFS2.4 删除HDFS文件和目录 3. 查看YARN集群状态4. 实战总结 1. 查看HDFS集群状态 …

EMS专题 | 5个必须知道的温度监测系统入门知识

在保护温度敏感资产方面&#xff0c;可靠的温度监测技术扮演着至关重要的角色。为了帮助您深入了解这一关键技术&#xff0c;我们特别推出了EMS&#xff08;环境监测系统&#xff09;专题文章系列。内容将由浅入深&#xff0c;从基础原理到实际应用&#xff0c;从行业标准到解决…

代码随想录-字符串-反转字符串中的单词

题目 题解 法一:纯粹为了做出本题&#xff0c;暴力解 没有技巧全是感情 class Solution {public String reverseWords(String s) {//首先去除首尾空格s s.trim();String[] strs s.split("\\s");StringBuilder sb new StringBuilder();//定义一个公共的字符反转…

关于Android Studio Koala Feature Drop | 2024.1.2下载不了插件的解决办法

解决 androidStudio Settings->Plugins下载插件&#xff0c;点击install后没反应&#xff0c;同时插件描述相关显示不出来 第一步&#xff1a; 第二步&#xff1a; 点击设置&#xff0c;勾选Auto-detect proxy settings&#xff0c;输入网址 https://plugins.jetbrains.com…