SpringCloud学习(13)-SpringCloudAlibaba-Seata

一、介绍:

Seata是阿里巴巴旗下的产品,是一款开源的分布式事务解决方案,旨在解决分布式事务问题。

我们有必要先了解一下分布式事务:

在微服务体系中,每一个模块都有连接一个数据库,这一点与单体项目是不同的,单体项目就连接一个数据库。

那么如果有多个模块之间相互调用,怎样保证各个模块之间的事务一致性?由此引出了分布式事务。

在同一个数据库中,我们要保证事物的一致性是很简单的。因为MySQL是基于单机事物的,所以一旦遇到跨库的场景,那么MySQL数据库就无能为力了。在这种情景下,seata蕴育而生。

二、Seata的下载和启动:

seata的官网:Apache Seata

seata的下载地址:

https://github.com/apache/incubator-seata/releases/download/v2.0.0/seata-server-2.0.0.zip

e4ea6f2337d549fe95bae2709f3d508a.png

有三个概念要先了解:

  1. TC是事务协调器(就是Seata本身),负责管理全局事务的执行过程。它生成全局唯一的事务ID,并协调各个分支事务的提交或回滚,以确保数据的一致性。有且仅有一个

  2. TM是事务管理器,(标注全局@GlobalTransactional启动入口动作的微服务模块)负责发起全局事务的提交或回滚请求,并与TC交互以执行相应操作。它与业务逻辑代码交互,触发分支事务的执行,并根据TC的指示来决定全局事务的最终状。有且仅有一个

  3. .RM是资源管理器,(各个模块的MySQL数据库本身)负责管理分支事务的资源,如数据库、消息队列、缓存等。它接收TC的指令并执行相应的事务操作,以确保分支事务的一致性。可以有多个

总的来说,TC负责全局事务的协调和管理,TM负责全局事务的发起和控制,RM负责具体资源的管理和事务操作。它们共同协作,实现了Seata分布式事务框架的核心功能,确保分布式系统中事务的一致性和可靠性。

下载完seata之后,要使用seata要现在本地的MySQL数据库中新建一个数据库seata,来记录seata在运行过程中的信息;

CREATE DATABASE seata;USE seata;

sql脚本:
 

create table branch_table
(branch_id         bigint        not nullprimary key,xid               varchar(128)  not null,transaction_id    bigint        null,resource_group_id varchar(32)   null,resource_id       varchar(256)  null,branch_type       varchar(8)    null,status            tinyint       null,client_id         varchar(64)   null,application_data  varchar(2000) null,gmt_create        datetime(6)   null,gmt_modified      datetime(6)   null
);create index idx_xidon branch_table (xid);create table distributed_lock
(lock_key   char(20)    not nullprimary key,lock_value varchar(20) not null,expire     bigint      null
);INSERT INTO seata.distributed_lock (lock_key, lock_value, expire) VALUES ('AsyncCommitting', ' ', 0);
INSERT INTO seata.distributed_lock (lock_key, lock_value, expire) VALUES ('RetryCommitting', ' ', 0);
INSERT INTO seata.distributed_lock (lock_key, lock_value, expire) VALUES ('RetryRollbacking', ' ', 0);
INSERT INTO seata.distributed_lock (lock_key, lock_value, expire) VALUES ('TxTimeoutCheck', ' ', 0);create table global_table
(xid                       varchar(128)  not nullprimary key,transaction_id            bigint        null,status                    tinyint       not null,application_id            varchar(32)   null,transaction_service_group varchar(32)   null,transaction_name          varchar(128)  null,timeout                   int           null,begin_time                bigint        null,application_data          varchar(2000) null,gmt_create                datetime      null,gmt_modified              datetime      null
);create index idx_status_gmt_modifiedon global_table (status, gmt_modified);create index idx_transaction_idon global_table (transaction_id);create table lock_table
(row_key        varchar(128)      not nullprimary key,xid            varchar(128)      null,transaction_id bigint            null,branch_id      bigint            not null,resource_id    varchar(256)      null,table_name     varchar(32)       null,pk             varchar(36)       null,status         tinyint default 0 not null comment '0:locked ,1:rollbacking',gmt_create     datetime          null,gmt_modified   datetime          null
);create index idx_branch_idon lock_table (branch_id);create index idx_statuson lock_table (status);create index idx_xidon lock_table (xid);

创建好库和表之后,更改seata的内容来启动seata:
在seata的conf文件夹下,更改application.yml文件,启动seata:

#  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: ${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:
# 配置方式nacosconfig:type: nacos# support: nacos, consul, apollo, zk, etcd3nacos:server-addr: localhost: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.properties
# 注册方式 nacosregistry:# support: nacos, eureka, redis, zk, consul, etcd3, sofatype: nacos# preferred-networks: 30.240.*nacos:application: seata-serverserver-addr: localhost:8848group: SEATA_GROUPnamespace:cluster: defaultusername: nacospassword: nacos
# 存储方式 db mysqlstore:mode: db# support: file 、 db 、 redis 、 raftdb:datasource: druiddb-type: mysqldriver-class-name: com.mysql.cj.jdbc.Driverurl: jdbc:mysql://localhost:3306/db2024?characterEncoding=utf-8&useSSL=false&serverTimezone=GMT%2B8&rewriteBatchedStatements=true&allowPublicKeyRetrieval=trueuser: rootpassword: 123456min-conn: 10max-conn: 100global-table: global_tablebranch-table: branch_tablelock-table: lock_tabledistributed-lock-table: distributed_lockquery-limit: 1000max-wait: 5000#  server:#    service-port: 8091 #If not configured, the default is '${server.port} + 1000'security:secretKey: SeataSecretKey0c382ef121d778043159209298fd40bf3850a017tokenValidityInMilliseconds: 1800000ignore:urls: /,/**/*.css,/**/*.js,/**/*.html,/**/*.map,/**/*.svg,/**/*.png,/**/*.jpeg,/**/*.ico,/api/v1/auth/login,/metadata/v1/**

根据你nacos、MySQL表的信息,进行相应的更改;

先启动nacos、再启动seata;(seata的启动在bin下的seata-server.bat)

可以看到seata已经作为一个模块注册进了nacos中;

访问7091端口,可以看到seata的图形化界面(用户名和密码都是seata)

三、Seata测试Demo(AT模式)


业务说明:订单服务→库存服务→支付服务:下订单 --->减库存---->扣余额---->修改(订单)状态

maven依赖:

<dependency><groupId>com.alibaba.cloud</groupId><artifactId>spring-cloud-starter-alibaba-seata</artifactId>
</dependency>

配置文件application(seata相关):

seata:registry:type: nacosnacos:server-addr: localhost:8848namespace: ""group: SEATA_GROUPapplication: seata-servertx-service-group: default_tx_group #事务组,由他获得TC服务的集群名称service:vgroup-mapping: #源码默认名字 default_tx_group defaultdefault_tx_group: default #事务组与TC服务集群的映射关系data-source-proxy-mode: AT  #默认是AT 如果是AT可不写logging:level:io:seata: info

主要业务方法:

其中int i =10/0;用于测试异常情况

@Override@GlobalTransactional(name = "create-order-transaction", rollbackFor = Exception.class)public void create(Order order) {// xid全局事务检查String xid = RootContext.getXID();// 1. 新建订单log.info("-------------> 开始新建订单, XID: {}", xid);order.setStatus(0);int result = orderMapper.insertSelective(order);Order orderFromDB;if (result > 0) {orderFromDB = orderMapper.selectOne(order);log.info("-------------> 新建订单成功, OrderInfo: {}", orderFromDB);// 2. 扣减库存log.info("-------------> 开始扣减库存");storageFeignApi.decrease(orderFromDB.getProductId(), orderFromDB.getCount());log.info("-------------> 扣减库存成功");// 3. 扣减账户余额log.info("-------------> 开始扣减余额");accountFeignApi.decrease(order.getUserId(), order.getMoney());log.info("-------------> 扣余额存成功");int i = 10/0;// 4. 修改订单状态log.info("-------------> 开始修改订单状态");Example whereCondition = new Example(Order.class);Example.Criteria criteria = whereCondition.createCriteria();criteria.andEqualTo("id", orderFromDB.getId());criteria.andEqualTo("status", 0);orderFromDB.setStatus(1);int updateResult = orderMapper.updateByExampleSelective(orderFromDB, whereCondition);log.info("-------------> 修改订单状态成功");}log.info("-------------> 结束新建订单, XID: {}", xid);}

调用接口前三个数据库,三张表以及对应数据库undo_log表如下:

执行过程中(断点在异常语句处)数据库及seata控制台:

执行完成:

结果:可以看到在过程中记录添加进数据库并进行了相关记录,异常后进行了回滚。

四、总结:

我们之前的步骤都是建立在seata的AT模式上;

AT 模式是 Seata 创新的一种非侵入式的分布式事务解决方案,Seata 在内部做了对数据库操作的代理层,我们使用 Seata AT 模式时,实际上用的是 Seata 自带的数据源代理 DataSourceProxy,Seata 在这层代理中加入了很多逻辑,比如插入回滚 undo_log 日志,检查全局锁等。

整体机制​

两阶段提交协议的演变:

  • 一阶段:业务数据和回滚日志记录在同一个本地事务中提交,释放本地锁和连接资源。
  • 二阶段:
    • 提交异步化,非常快速地完成。
    • 回滚通过一阶段的回滚日志进行反向补偿。

在一阶段,Seata 会拦截“业务 SQL”,

1  解析 SQL 语义,找到“业务 SQL”要更新的业务数据,在业务数据被更新前,将其保存成“before image”,

2  执行“业务 SQL”更新业务数据,在业务数据更新之后,

3  其保存成“after image”,最后生成行锁。

以上操作全部在一个数据库事务内完成,这样保证了一阶段操作的原子性。

1d9682c3d0764438b93d426675f8e726.png

二阶段分为两种情况:

1、正常提交:

二阶段如是顺利提交的话,

因为“业务 SQL”在一阶段已经提交至数据库,所以Seata框架只需将一阶段保存的快照数据和行锁删掉,完成数据清理即可。

81310ceb73094a0e8fd59a286b9f78c3.png

2、异常回滚:

二阶段如果是回滚的话,Seata 就需要回滚一阶段已经执行的“业务 SQL”,还原业务数据。

回滚方式便是用“before image”还原业务数据;但在还原前要首先要校验脏写,对比“数据库当前业务数据”和 “after image”,

如果两份数据完全一致就说明没有脏写,可以还原业务数据,如果不一致就说明有脏写,出现脏写就需要转人工处理。

a48275f6955343c99d6d217a9af2148a.png

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

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

相关文章

10-热点文章-定时计算

xxl-Job分布式任务调度 1 今日内容 1.1 需求分析 目前实现的思路&#xff1a;从数据库直接按照发布时间倒序查询 问题1&#xff1a; 如何访问量较大&#xff0c;直接查询数据库&#xff0c;压力较大 问题2&#xff1a; 新发布的文章会展示在前面&#xff0c;并不是热点文章 …

算法打卡26

今日任务&#xff1a; 1&#xff09;332.重新安排行程 2&#xff09;51.N皇后 3&#xff09;37.解数独 332.重新安排行程 题目链接&#xff1a;332. 重新安排行程 - 力扣&#xff08;LeetCode&#xff09; 给定一个机票的字符串二维数组 [from, to]&#xff0c;子数组中的两个…

菜狗学前端之JS高级笔记

老样子。复制上来的图片都没了&#xff0c;想看原版可以移步对应资源下载(资源刚上传&#xff0c;还在审核中) (免费) JS高级笔记https://download.csdn.net/download/m0_58355897/89102910 一些前提概念 一 什么是js高级 js高级是对js基础语法的一个补充说明&#xff0c;本质…

高效稳定转换!PW2205芯片轻松实现12V/24V转5V/3.3V 5A输出

在电子设备蓬勃发展的今天&#xff0c;高效稳定的电源转换技术成为了推动行业进步的关键。PW2205平芯微芯片推出的高效同步降压DC-DC转换器&#xff0c;以其出色的性能和广泛的应用领域&#xff0c;成为了市场上的热门选择。 PW2205转换器凭借其卓越的性能&#xff0c;为各类电…

AI智能滤镜解决方案,全新的视觉创作体验

一张精美的图片&#xff0c;一段引人入胜的视频&#xff0c;往往能够瞬间抓住观众的眼球&#xff0c;为企业带来不可估量的商业价值。然而&#xff0c;如何快速、高效地制作出高质量的视觉内容&#xff0c;一直是困扰众多企业的难题。美摄科技凭借其领先的AI智能滤镜解决方案&a…

电脑实时监控软件分享|五个好用的实时屏幕监控软件

电脑实时监控软件是一种专门设计用于实时监控和记录电脑用户操作行为、系统状态以及网络活动的软件工具。 这类软件主要服务于企业、教育机构、家庭或个人用户&#xff0c;用于确保网络安全、提升工作效率、监督员工行为、保护儿童在线安全、防止数据泄露等多种目的。 针对企业…

面试(01)————JVM篇,最大白话的一集,常见概念的讲解以及GC监控调优等等

一、JDK体系结构图 二、JVM整体架构 三、JVM组成 3.1、JVM内存区域的执行底层原理 ​编辑 3.1.1、程序计数器 3.1.2、堆栈关系的发现 3.1.3、方法去和堆的关系 3.1.4、堆&#xff08;重点&#xff09; 3.1.4.1、可达性分析算法 3.1、内存泄漏测试以及堆区的GC监控 3.…

电脑硬盘分区表的两种格式:MBR 和 GPT

电脑硬盘分区表的两种格式&#xff1a;MBR 和 GPT 段子手168 2024-4-5 电脑硬盘分区表有两种格式&#xff1a;MBR 和 GPT&#xff1a; 一、MBR 分区表 1.MBR 是主引导记录 (Master Boot Record) 的英文缩写 在传统&#xff08;Legacy&#xff09;硬盘分区模式中&#xff0c…

零基础入门NLP - 新闻文本分类比赛方案分享 nano- Rank1

nano- 康一帅 简介 环境 Tensorflow 1.14.0Keras 2.3.1bert4keras 0.8.4 文件说明 EDA&#xff1a;用于探索性数据分析。data_utils&#xff1a;用于预训练语料的构建。pretraining&#xff1a;用于Bert的预训练。train&#xff1a;用于新闻文本分类模型的训练。pred&a…

环形链表 II - LeetCode 热题 26

大家好&#xff01;我是曾续缘&#x1f61b; 今天是《LeetCode 热题 100》系列 发车第 26 天 链表第 5 题 ❤️点赞 &#x1f44d; 收藏 ⭐再看&#xff0c;养成习惯 环形链表 II 给定一个链表的头节点 head &#xff0c;返回链表开始入环的第一个节点。 如果链表无环&#xf…

每日OJ题_两个数组dp④_力扣44. 通配符匹配

目录 力扣44. 通配符匹配 解析代码 力扣44. 通配符匹配 44. 通配符匹配 难度 困难 给你一个输入字符串 (s) 和一个字符模式 (p) &#xff0c;请你实现一个支持 ? 和 * 匹配规则的通配符匹配&#xff1a; ? 可以匹配任何单个字符。* 可以匹配任意字符序列&#xff08;包…

全面了解网络性能监测:从哪些方面进行监测?

目录 摘要 引言 CPU内存监控 磁盘监控 网络监控 GPU监控 帧率监控 总结 摘要 本文介绍了网络性能监测的重要性&#xff0c;并详细介绍了一款名为克魔助手的应用开发工具&#xff0c;该工具提供了丰富的性能监控功能&#xff0c;包括CPU、内存、磁盘、网络等指标的实时…

[C语言]——柔性数组

目录 一.柔性数组的特点 二.柔性数组的使用 三.柔性数组的优势 C99中&#xff0c;结构体中的最后⼀个元素允许是未知大小的数组&#xff0c;这就叫做『柔性数组』成员。 typedef struct st_type //typedef可以不写 { int i;int a[0];//柔性数组成员 }type_a; 有些编译器会…

B. Burning Midnight Oil Codeforces Round 112 (Div. 2)

题目链接&#xff1a; Problem - 165B - Codeforceshttps://codeforces.com/problemset/problem/165/B 题目大意&#xff1a; 最后写了至少n个&#xff0c;每次衰减k倍&#xff08;/k&#xff09;&#xff0c;问最初的v最小为多少。 思路&方法&#xff1a; 二分答案。 AC代…

2024零废弃日青山少年可持续工坊走进南湖社区

“零废弃”不代表完全不产生任何垃圾&#xff0c;而是一种“尽可能避免产生废弃”的生活态度&#xff0c;每一个人都可以从零开始&#xff0c;从日常的随手小事开始&#xff0c;珍惜每一件物品、珍视每一种情绪&#xff0c;为生活腾出更大的空间。 2024零废弃日&#xff0c;北…

JS 表单验证

点击注册的时候&#xff0c;渲染出来&#xff0c;验证码是自动获取出来的 html&#xff1a; <div class"div1">用户名<input type"text" id"yhm"><span id"span1"></span><br>密码<input type"…

《Git版本控制管理》笔记

第三章 起步 git --version查看版本号git --help查看帮助文档裸双破折号分离参数 git diff -w master origin – tools/Makefile将当前目录或任何目录转化为Git版本库 git init 初始化之后项目目录中&#xff0c;有名为.git的文件git status 查看git状态git commit 提供日志消…

贪心算法|135.分发糖果

力扣题目链接 class Solution { public:int candy(vector<int>& ratings) {vector<int> candyVec(ratings.size(), 1);// 从前向后for (int i 1; i < ratings.size(); i) {if (ratings[i] > ratings[i - 1]) candyVec[i] candyVec[i - 1] 1;}// 从后…

格式化字符串漏洞原理及其利用(附带pwn例题讲解)

写在前面&#xff1a; 本篇博客为本人原创&#xff0c;但非首发&#xff0c;首发在先知社区 原文链接&#xff1a; https://xz.aliyun.com/t/14253?time__1311mqmx9QiQi%3D0%3DDQoDsNOfptD8nDCFdNNK4D&alichlgrefhttps%3A%2F%2Fxz.aliyun.com%2Fu%2F74789各位师傅有兴趣…

JQuery(三)---【使用JQuery动态设置浏览器窗口尺寸、JQuery的遍历】

零.前言 JQuery(一)---【JQuery简介、安装、初步使用、各种事件】-CSDN博客 JQuery(二)---【使用JQuery对HTML、CSS进行操作】-CSDN博客 一.JQuery动态设置浏览器窗口尺寸大小 1.1width()和height()方法 width()&#xff1a;设置或者返回元素的宽度(不包括内边距、边框或外…