Seata学习

系列文章目录

JavaSE
基础知识、数据类型学习万年历项目代码逻辑训练习题
代码逻辑训练习题方法、数组学习图书管理系统项目
面向对象编程:封装、继承、多态学习封装继承多态习题常用类、包装类、异常处理机制学习
集合学习IO流、多线程学习仓库管理系统JavaSE项目
员工管理系统、多表查询、反射实现DBHelper学习DML、DDL、数据库对象学习
JavaWeb
网络编程、各种标签、CSS学习ECMAScript、BOM学习DOM、jQuery学习
Servlet、JSP、Cookie、Ajax学习融资管理系统JavaWeb项目
框架
MyBatis框架学习逆向工程、Spring框架IOC、AOP学习SpringMVC框架学习
SpringBoot框架学习招聘网站框架项目Vue介绍、窗体内操作、窗体间操作学习
Vue路由配置、网络请求访问框架项目、element组件介绍学习标准管理系统Vue项目
微服务
Linux安装、Nginx反向代理、负载均衡学习Docker学习Jenkins学习
Nexus学习Spring Security学习RabbitMQ学习
Redis学习MongoDB学习Nacos学习
Spring Session学习Spring Gateway学习JSR 303学习
OenFeign学习Dubbo学习Hystrix学习
Sentinel学习JMeter学习Seata学习


前言

本文我们要讲述:
Seata
代码自取
通过网盘分享的文件:241005_seata.zip
链接: https://pan.baidu.com/s/1xTs4uV-3VAiRCPzBjd-Qow?pwd=k25m 提取码: k25m


一、Seata介绍

1. Seata介绍

Seata是一个用于管理分布式事务的开源框架,由阿里巴巴集团开发并维护。它提供了一套分布式事务解决方案,旨在解决分布式系统中的事务一致性问题。

2. 三个核心角色

事务协调者(Transaction Coordinator,TC):负责维护整个分布式事务的状态,包括主事务和分支事务。

事务管理器(Transaction Manager,TM):负责管理事务的生命周期,决定事务何时开始、何时结束,以及提交或回滚事务。TM负责事务的提交和回滚操作。

资源管理器(Resource Manager,RM):监控分支事务的状态并与TC进行数据交互,将分支事务的状态告知TC。

3. 四种分布式事务的解决方案

AT(Auto-Commit):自动提交模式,通过使用数据库的本地事务来实现分布式事务的一致性。

TCC(Try-Confirm-Cancel):尝试-确认-取消模式,通过定义三个阶段的业务方法来实现分布式事务的一致性。

SAGA(Saga):Saga模式是一种长事务解决方案,通过定义一系列补偿操作来实现分布式事务的一致性。

XA(eXtended Architecture):XA模式是一种经典的两阶段提交(2PC)协议,通过协调TM和RM的工作来实现分布式事务的一致性。

对于高并发项目,Seata的AT模式可能不太适用,因为在中间操作时可能会有锁的存在,从而导致效率降低。在选择Seata的解决方案时,可以根据具体的业务场景和性能需求来进行选择。

二、Seata安装

1. 拉取docker镜像

docker pull seataio/seata-server:1.3.0

在这里插入图片描述

2. 拷贝配置文件

docker run -d --name seata -p 8091:8091 seataio/seata-server:1.3.0

在这里插入图片描述

2.1 创建目录

创建/usr/local/docker/seata目录

docker cp seata:/seata-server /usr/local/docker/seata

在这里插入图片描述

2.2 保存file.conf文件

在/usr/local/docker/seata/seata-server/resources文件夹下找到file.conf
将file改成db
在这里插入图片描述
更改数据库连接属性
在这里插入图片描述

3. 启动nacos

docker start nacos

在这里插入图片描述
创建命名空间,找到id:05c721d3-1298-4204-832d-60b94a84cbbd
在这里插入图片描述

4. 保存registry.conf文件

group无需更改,最好不要改
namespace写刚刚拿到的命名空间ID
在这里插入图片描述
在这里插入图片描述

5. 创建config.txt文件

文件内容

#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.my_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=

#If `store.mode,store.lock.mode,store.session.mode` are not equal to `file`, you can remove the configuration block.
store.file.dir=file_store/data
store.file.maxBranchSessionSize=16384
store.file.maxGlobalSessionSize=512
store.file.fileWriteBufferCacheSize=16384
store.file.flushDiskMode=async
store.file.sessionReloadReadSize=100

#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://192.168.43.8:3306/seata?useUnicode=true&rewriteBatchedStatements=true
store.db.user=root
store.db.password=123456
# ---------------------------------------------------
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

#These configurations are required if the `store mode` is `redis`. If `store.mode,store.lock.mode,store.session.mode` are not equal to `redis`, you can remove the configuration block.
store.redis.mode=single
store.redis.single.host=127.0.0.1
store.redis.single.port=6379
store.redis.sentinel.masterName=
store.redis.sentinel.sentinelHosts=
store.redis.maxConn=10
store.redis.minConn=1
store.redis.maxTotal=100
store.redis.database=0
store.redis.password=
store.redis.queryLimit=100

#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

需更改注释之间的数据库连接属性
在这里插入图片描述

6. 创建nacos-config.sh文件

#!/bin/sh
# 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.

while getopts ":h:p:g:t:u:w:" opt
do
  case $opt in
  h)
    host=$OPTARG
    ;;
  p)
    port=$OPTARG
    ;;
  g)
    group=$OPTARG
    ;;
  t)
    tenant=$OPTARG
    ;;
  u)
    username=$OPTARG
    ;;
  w)
    password=$OPTARG
    ;;
  ?)
    echo " USAGE OPTION: $0 [-h host] [-p port] [-g group] [-t tenant] [-u username] [-w password] "
    exit 1
    ;;
  esac
done

if [ -z ${host} ]; then
    host=localhost
fi
if [ -z ${port} ]; then
    port=8848
fi
if [ -z ${group} ]; then
    group="SEATA_GROUP"
fi
if [ -z ${tenant} ]; then
    tenant=""
fi
if [ -z ${username} ]; then
    username=""
fi
if [ -z ${password} ]; then
    password=""
fi

nacosAddr=$host:$port
contentType="content-type:application/json;charset=UTF-8"

echo "set nacosAddr=$nacosAddr"
echo "set group=$group"

urlencode() {
  length="${#1}"
  i=0
  while [ $length -gt $i ]; do
    char="${1:$i:1}"
    case $char in
    [a-zA-Z0-9.~_-]) printf $char ;;
    *) printf '%%%02X' "'$char" ;;
    esac
    i=`expr $i + 1`
  done
}

failCount=0
tempLog=$(mktemp -u)
function addConfig() {
  dataId=`urlencode $1`
  content=`urlencode $2`
  curl -X POST -H "${contentType}" "http://$nacosAddr/nacos/v1/cs/configs?dataId=$dataId&group=$group&content=$content&tenant=$tenant&username=$username&password=$password" >"${tempLog}" 2>/dev/null
  if [ -z $(cat "${tempLog}") ]; then
    echo " Please check the cluster status. "
    exit 1
  fi
  if [ "$(cat "${tempLog}")" == "true" ]; then
    echo "Set $1=$2 successfully "
  else
    echo "Set $1=$2 failure "
    failCount=`expr $failCount + 1`
  fi
}

count=0
COMMENT_START="#"
for line in $(cat $(dirname "$PWD")/config.txt | sed s/[[:space:]]//g); do
    if [[ "$line" =~ ^"${COMMENT_START}".*  ]]; then
      continue
    fi
    count=`expr $count + 1`
	  key=${line%%=*}
    value=${line#*=}
	  addConfig "${key}" "${value}"
done

echo "========================================================================="
echo " Complete initialization parameters,  total-count:$count ,  failure-count:$failCount "
echo "========================================================================="

if [ ${failCount} -eq 0 ]; then
	echo " Init nacos config finished, please start seata-server. "
else
	echo " init nacos config fail. "
fi

7. 导入nacos配置

首先准备
file.conf、
registry.conf、
config.txt、
nacos-config.sh
以上四个文件备份到桌面,运行如下文件清除seata-server及其下所有文件

cd /usr/local/docker/seata
rm -rf seata-server

在seata文件夹下创建
在这里插入图片描述
在nacos文件夹里放入nacos-config.sh

cd /usr/local/docker/seata/nacos
chmod +x nacos-config.sh
ll

变成绿色为操作成功
在这里插入图片描述

sh nacos-config.sh -h 192.168.43.143 -p 8848 -g SEATA_GROUP -t 05c721d3-1298-4204-832d-60b94a84cbbd -u nacos -w nacos

在这里插入图片描述
会出现上图的错误,运行如下语句就能正常运行

sed -i 's/\r//' nacos-config.sh
sh nacos-config.sh -h 192.168.43.143 -p 8848 -g SEATA_GROUP -t 05c721d3-1298-4204-832d-60b94a84cbbd -u nacos -w nacos

在这里插入图片描述
删除seata下的所有文件(就俩文件,手动删更快)
在这里插入图片描述

8. 复制配置文件

创建config文件夹
将file.conf和registry.conf复制到config文件夹下
运行如下授权语句

cd /usr/local/docker/seata
chmod 777 config

在这里插入图片描述

9. 关闭并删除之前的seata容器

docker stop seata
docker rm seata

在这里插入图片描述

10. 开启mysql容器

docker start mm

在这里插入图片描述
在这里插入图片描述

11. 测试并创建连接

在这里插入图片描述

11. 创建seata数据库

在这里插入图片描述

12. 创建表

DROP TABLE
IF
	EXISTS `global_table`;
CREATE TABLE `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 ( 64 ),
	`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` ) 
);
DROP TABLE
IF
	EXISTS `branch_table`;
CREATE TABLE `branch_table` (
	`branch_id` BIGINT NOT NULL,
	`xid` VARCHAR ( 128 ) NOT NULL,
	`transaction_id` BIGINT,
	`resource_group_id` VARCHAR ( 32 ),
	`resource_id` VARCHAR ( 256 ),
	`lock_key` VARCHAR ( 128 ),
	`branch_type` VARCHAR ( 8 ),
	`status` TINYINT,
	`client_id` VARCHAR ( 64 ),
	`application_data` VARCHAR ( 2000 ),
	`gmt_create` datetime,
	`gmt_modified` datetime,
	PRIMARY KEY ( `branch_id` ),
	KEY `idx_xid` ( `xid` ) 
);
DROP TABLE
IF
	EXISTS `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 ( 100 ),
	`pk` VARCHAR ( 36 ),
	`gmt_create` datetime,
	`gmt_modified` datetime,
	PRIMARY KEY ( `row_key` ) 
);

创建语句如上

13. 启动seata

docker run --name seata \
-p 8091:8091 \
-e SEATA_IP=192.168.43.143 \
-e SEATA_PORT=8091 \
-e SEATA_CONFIG_NAME=file:/root/seata-config/registry \
-v /usr/local/docker/seata/config:/root/seata-config  \
-d seataio/seata-server:1.3.0

在这里插入图片描述
运行如下语句看到8091即为成功

docker logs -f seata

在这里插入图片描述

三、普通事务回滚

1. 项目基础

一些基础的项目结构无需我们编写,以提供
通过网盘分享的文件:241005_seata.zip
链接: https://pan.baidu.com/s/1xTs4uV-3VAiRCPzBjd-Qow?pwd=k25m 提取码: k25m
以下所有操作都会在两个项目同时进行,如果是单个项目进行的会额外标出
以下所有操作都会在两个项目同时进行,如果是单个项目进行的会额外标出
以下所有操作都会在两个项目同时进行,如果是单个项目进行的会额外标出

2. 更改application.yml内数据库连接属性

在这里插入图片描述

3. 创建score数据库

在这里插入图片描述
在这里插入图片描述
创建score数据库和user数据库
score数据库里有score表和undo_log表
user数据库里有user表和undo_log表,两者的undo_log表相同
表结构如下:

CREATE TABLE `score`  (
  `id` varchar(50)  NOT NULL,
  `name` varchar(50)  NULL,
  `score` double(7, 2) NULL ,
  PRIMARY KEY (`id`) USING BTREE
) 

CREATE TABLE `user`  (
  `id` varchar(50)  NOT NULL,
  `name` varchar(50)  NULL,
  `password` varchar(50)  NULL,
  PRIMARY KEY (`id`) USING BTREE
) 
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. 运行项目

4.1 正常运行

在这里插入图片描述
在这里插入图片描述

4.2 异常运行测试回滚

项目1内 添加异常语句,测试回滚
在这里插入图片描述
重启项目
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
出错了,但是发现数据库内两个都添加成功了

5. 添加普通的事务回滚

在两个项目的UserServiceImpl/ScoreServiceImpl中添加注解

    @GlobalTransactional(rollbackFor = Exception.class)

再次启动项目
user的post出错添加失败
在这里插入图片描述
但是score的请求成功了
在这里插入图片描述
事务没有实现原子性
如何解决呢

四、Seata事务回滚

依旧是两个项目同时添加

1. 添加依赖

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

2. 启动类添加注释

@SpringBootApplication(exclude = DataSourceAutoConfiguration.class)

3. 修改application.yml配置文件

修改为如下格式

server:
  port: 100

spring:
  datasource:
    driver-class-name: com.mysql.cj.jdbc.Driver
    url: jdbc:mysql://192.168.43.143:3306/user
    username: root
    password: 123456

mybatis:
  mapper-locations: classpath:com/jr/mapper/*.xml
  type-aliases-package: com.jr.entry

seata:
  application-id: ${spring.application.name}
  enabled: true
  tx-service-group: my_tx_group
  registry:
    type: nacos
    nacos:
      server-addr: 192.168.43.143:8848
      namespace: 05c721d3-1298-4204-832d-60b94a84cbbd
      group: SEATA_GROUP
      username: nacos
      password: nacos
  config:
    type: nacos
    nacos:
      server-addr: 192.168.43.143:8848
      namespace: 05c721d3-1298-4204-832d-60b94a84cbbd
      group: SEATA_GROUP
      username: nacos
      password: nacos
  service:
    vgroup-mapping:
      my_tx_group: default

feign:
  httpclient:
    connection-timeout: 600000
    connection-timer-repeat: 30000

4. 更改事务注解

@GlobalTransactional(rollbackFor = Exception.class,timeoutMills = 300000)

在这里插入图片描述

5. 启动项目

5.1 有错误时

两个都不添加了
在这里插入图片描述
在这里插入图片描述

5.2 无错误时

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
都能请求成功


总结

本文讲述了:
Seata:项目间事务回滚
在下攸攸太上,女朋友超级可爱。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

攸攸太上

感谢支持

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值