Cyan Blog Cyan Blog
首页
  • Java (opens new window)
  • JUC (opens new window)
  • JVM (opens new window)
  • Redis

    • Redis安装 (opens new window)
    • Redis基础 (opens new window)
    • Redis实战 (opens new window)
    • Redis集群安装 (opens new window)
    • Redis分布式缓存 (opens new window)
    • Redis多级缓存 (opens new window)
    • Redis原理 (opens new window)
  • 管理工具

    • Maven (opens new window)
    • Git (opens new window)
  • SSM

    • Spring (opens new window)
    • SpringBoot (opens new window)
    • Mybatis (opens new window)
    • MybatisPlus (opens new window)
  • 微服务

    • Docker (opens new window)
    • RabbitMQ (opens new window)
    • SpringCloud (opens new window)
    • Dubbo (opens new window)
    • MongoDB (opens new window)
    • Zookeeper (opens new window)
  • Java面试题 (opens new window)
  • JUC面试题 (opens new window)
  • JVM面试题 (opens new window)
  • Linux面试题 (opens new window)
  • SQL面试题 (opens new window)
  • Maven面试题 (opens new window)
  • Redis面试题 (opens new window)
  • SSM面试题 (opens new window)
  • SpringCloud面试题 (opens new window)
  • Linux (opens new window)
  • C++ (opens new window)
  • 数据库

    • MySQL (opens new window)
    • NoSQL (opens new window)
  • 软件测试

    • 软件测试 (opens new window)
  • 加密解密 (opens new window)
  • bilibili字幕提取 (opens new window)
  • 道理 (opens new window)
  • 关于博主

    • Github (opens new window)
    • CSDN (opens new window)
  • 关于本站

    • 如何搭建博客网站 (opens new window)
首页
  • Java (opens new window)
  • JUC (opens new window)
  • JVM (opens new window)
  • Redis

    • Redis安装 (opens new window)
    • Redis基础 (opens new window)
    • Redis实战 (opens new window)
    • Redis集群安装 (opens new window)
    • Redis分布式缓存 (opens new window)
    • Redis多级缓存 (opens new window)
    • Redis原理 (opens new window)
  • 管理工具

    • Maven (opens new window)
    • Git (opens new window)
  • SSM

    • Spring (opens new window)
    • SpringBoot (opens new window)
    • Mybatis (opens new window)
    • MybatisPlus (opens new window)
  • 微服务

    • Docker (opens new window)
    • RabbitMQ (opens new window)
    • SpringCloud (opens new window)
    • Dubbo (opens new window)
    • MongoDB (opens new window)
    • Zookeeper (opens new window)
  • Java面试题 (opens new window)
  • JUC面试题 (opens new window)
  • JVM面试题 (opens new window)
  • Linux面试题 (opens new window)
  • SQL面试题 (opens new window)
  • Maven面试题 (opens new window)
  • Redis面试题 (opens new window)
  • SSM面试题 (opens new window)
  • SpringCloud面试题 (opens new window)
  • Linux (opens new window)
  • C++ (opens new window)
  • 数据库

    • MySQL (opens new window)
    • NoSQL (opens new window)
  • 软件测试

    • 软件测试 (opens new window)
  • 加密解密 (opens new window)
  • bilibili字幕提取 (opens new window)
  • 道理 (opens new window)
  • 关于博主

    • Github (opens new window)
    • CSDN (opens new window)
  • 关于本站

    • 如何搭建博客网站 (opens new window)
  • SSM

  • SpringBoot

  • SpringCloud

    • SpringCloud
    • Nacos
    • OpenFeign
    • Sentinel
    • Gateway
    • Seata——分布式事务
      • 介绍
      • 环境搭建
      • 事务模式
      • 总结
  • Docker
  • Dubbo
  • MongoDB
  • Zookeeper
  • Spring生态
  • SpringCloud
2025-05-30
0
0
目录

Seata——分布式事务

、

# 介绍

在单体项目的事务中,事务的回滚和提交是针对一个连接的,

而在分布式系统中,每个服务都有对应的数据库,当一个服务的事务执行失败进行回滚时由于其他服务的事务不在同一个连接中,无法回滚其他事务

seata就是用来解决分布式结构中的事务问题,保证多个事务一起回滚

官网

# 环境搭建

# 搭建微服务

创建多个model工程,并在services中添加model聚合

# SQL

启动⼀个数据库,然后导入如下sql文件

CREATE DATABASE IF NOT EXISTS `storage_db`;
USE `storage_db`;
DROP TABLE IF EXISTS `storage_tbl`;
CREATE TABLE `storage_tbl` (
 `id` int(11) NOT NULL AUTO_INCREMENT,
 `commodity_code` varchar(255) DEFAULT NULL,
 `count` int(11) DEFAULT 0,
 PRIMARY KEY (`id`),
 UNIQUE KEY (`commodity_code`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
INSERT INTO storage_tbl (commodity_code, count) VALUES ('P0001', 100);
INSERT INTO storage_tbl (commodity_code, count) VALUES ('B1234', 10);
-- 注意此处0.3.0+ 增加唯⼀索引 ux_undo_log
DROP TABLE IF EXISTS `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;
CREATE DATABASE IF NOT EXISTS `order_db`;
USE `order_db`;
DROP TABLE IF EXISTS `order_tbl`;
CREATE TABLE `order_tbl` (
 `id` int(11) NOT NULL AUTO_INCREMENT,
 `user_id` varchar(255) DEFAULT NULL,
 `commodity_code` varchar(255) DEFAULT NULL,
 `count` int(11) DEFAULT 0,
 `money` int(11) DEFAULT 0,
 PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
-- 注意此处0.3.0+ 增加唯⼀索引 ux_undo_log
DROP TABLE IF EXISTS `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;
CREATE DATABASE IF NOT EXISTS `account_db`;
USE `account_db`;
DROP TABLE IF EXISTS `account_tbl`;
CREATE TABLE `account_tbl` (
 `id` int(11) NOT NULL AUTO_INCREMENT,
 `user_id` varchar(255) DEFAULT NULL,
 `money` int(11) DEFAULT 0,
 PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
INSERT INTO account_tbl (user_id, money) VALUES ('1', 10000);
-- 注意此处0.3.0+ 增加唯⼀索引 ux_undo_log
DROP TABLE IF EXISTS `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;

# seata-server

下载:https://seata.apache.org/zh-cn/download/seata-server/

解压并启动: seata-server.bat

# 微服务配置⭐

# 依赖

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

# 配置

每个微服务创建file.comf文件

#
# Licensed to the Apache Software Foundation (ASF) under one or more
# contributor license agreements. See the NOTICE file distributed with
# this work for additional information regarding copyright ownership.
# The ASF licenses this file to You 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 implie
d.
# See the License for the specific language governing permissions and
# limitations under the License.
#
transport {
 # tcp, unix-domain-socket
 type = "TCP"
 #NIO, NATIVE
 server = "NIO"
 #enable heartbeat
 heartbeat = true
 # the tm client batch send request enable
 enableTmClientBatchSendRequest = false
 # the rm client batch send request enable
 enableRmClientBatchSendRequest = true
 # the rm client rpc request timeout
 rpcRmRequestTimeout = 2000
 # the tm client rpc request timeout
 rpcTmRequestTimeout = 30000
 # the rm client rpc request timeout
 rpcRmRequestTimeout = 15000
 #thread factory for netty
 threadFactory {
 bossThreadPrefix = "NettyBoss"
 workerThreadPrefix = "NettyServerNIOWorker"
 serverExecutorThread-prefix = "NettyServerBizHandler"
 shareBossWorker = false
 clientSelectorThreadPrefix = "NettyClientSelector"
 clientSelectorThreadSize = 1
 clientWorkerThreadPrefix = "NettyClientWorkerThread"
 # netty boss thread size
 bossThreadSize = 1
 #auto default pin or 8
 workerThreadSize = "default"
 }
 shutdown {
 # when destroy server, wait seconds
 wait = 3
 }
 serialization = "seata"
 compressor = "none"
}
service {
 #transaction service group mapping
 vgroupMapping.default_tx_group = "default"
 #only support when registry.type=file, please don't set multiple addres
ses
 default.grouplist = "127.0.0.1:8091"
 #degrade, current not support
 enableDegrade = false
 #disable seata
 disableGlobalTransaction = false
}
client {
 rm {
 asyncCommitBufferLimit = 10000
 lock {
 retryInterval = 10
 retryTimes = 30
 retryPolicyBranchRollbackOnConflict = true
 }
 reportRetryCount = 5
 tableMetaCheckEnable = false
 tableMetaCheckerInterval = 60000
 reportSuccessEnable = false
 sagaBranchRegisterEnable = false
 sagaJsonParser = "fastjson"
 sagaRetryPersistModeUpdate = false
 sagaCompensatePersistModeUpdate = false
 tccActionInterceptorOrder = -2147482648 #Ordered.HIGHEST_PRECEDENCE
+ 1000
 sqlParserType = "druid"
 branchExecutionTimeoutXA = 60000
 connectionTwoPhaseHoldTimeoutXA = 10000
 }
 tm {
 commitRetryCount = 5
 rollbackRetryCount = 5
 defaultGlobalTransactionTimeout = 60000
 degradeCheck = false
 degradeCheckPeriod = 2000
 degradeCheckAllowTimes = 10
 interceptorOrder = -2147482648 #Ordered.HIGHEST_PRECEDENCE + 1000
 }
 undo {
 dataValidation = true
 onlyCareUpdateColumns = true
 logSerialization = "jackson"
 logTable = "undo_log"
 compress {
 enable = true
 # allow zip, gzip, deflater, lz4, bzip2, zstd default is zip
 type = zip
 # if rollback info size > threshold, then will be compress
 # allow k m g t
 threshold = 64k
 }
 }
 loadBalance {
 type = "XID"
 virtualNodes = 10
 }
}
log {
 exceptionRate = 100
}
tcc {
 fence {
 # tcc fence log table name
 logTableName = tcc_fence_log
 # tcc fence log clean period
 cleanPeriod = 1h
 }
}

# 使用注解@GlobalTransaction

# 事务模式

二阶提交协议原理

image-20250531192254689

# AT(推荐模式)

AT模式是第一阶段所有的数据都已经提交了,即使后来的提交或回滚,第二阶段无论何时执行,不会让第一阶段的事物进行阻塞,

所以at模式的性能更高一点,

而Seata在底层默认使用的就是AT模式,

# XA

XA依然是二阶提交协议,第一阶段数据库去来执行SQL,第二阶段如果成功则去提交,如果失败则去回滚,

但是XA协议的特点就是,第一阶段它并不会给本地数据库真正提交数据,它会阻塞住这个事务请求,只有在第二阶段确认要提交以后真正去提交,

所以相当于对数据库的操作,那张表的事务所会从第一阶段就开始占用事物,一开始就使用了阻塞模式,所以性能会比较低下,

想要切换为XA也非常简单,只需要在每一个应用的application.yml配置文件

seata: 
	data-source-proxy-mode: XA

无论是AT还是XA它们都是一个全自动模式,而且代码不用修改任何一行,只需要加一个全局事务注解

# TCC

TCC是手动模式的,还是二阶提交协议,需要自定义准备、提交、回滚三个阶段

适合用于夹杂非数据库的事务代码,需要自己编写提交、回滚操作逻辑的

# Saga(了解)

适用于长事务,一个事务完成后消息通知下一个事务进行处理,如果失败消息通知之前的 事务执行自定义的回滚,执行补偿逻辑

最终一致性解决方案:基于消息模式,可以直接使用消息队列,没必要使用Seata了。

# 总结

image-20250531192635805

上次更新: 2025/6/10 17:21:17
Gateway
Docker

← Gateway Docker→

最近更新
01
md
06-10
02
Redis
06-10
03
HBase
06-10
更多文章>
Theme by Vdoing | Copyright © 2025-2025 Cyan Blog
  • 跟随系统
  • 浅色模式
  • 深色模式
  • 阅读模式