关键词:
Spring Cloud Alibaba Seata 分布式事务解决方案
一、分布式事务问题
- 一次业务操作需要跨多个数据源或者需要跨多个系统进行远程调用,就会产生分布式事务问题。
举例:
用户购买商品的业务逻辑。整个业务逻辑由3个微服务提供支持:
- 仓储服务:对给定的商品扣除仓储数量。
- 订单服务:根据采购需求创建订单。
- 帐户服务:从用户帐户中扣除余额。
单体应用被拆分成微服务应用,原来的三个模块被拆分成三个独立的应用,分别使用三个独立的数据源,业务操作需要调用三个服务来完成。此时每个服务内部的数据一致性由本地事务来保证,但是全局数据一致性问题是无法保证的。
二、Seata简介
Seata官网地址:http://seata.io/zh-cn/
- Seata是一款开源的分布式事务解决方案,致力于在微服务架构下提供高性能和简单易用的分布式事务服务。Seata 将为用户提供了 AT、TCC、SAGA 和 XA 事务模式,为用户打造一站式的分布式解决方案。
Seata术语:
-
TC (Transaction Coordinator) - 事务协调者
维护全局和分支事务的状态,驱动全局事务提交或回滚。 -
TM (Transaction Manager) - 事务管理器
定义全局事务的范围:开始全局事务、提交或回滚全局事务。 -
RM (Resource Manager) - 资源管理器
管理分支事务处理的资源,与TC交谈以注册分支事务和报告分支事务的状态,并驱动分支事务提交或回滚。
Seata处理过程:
- TM向TC申请开启一个全局事务,全局事务创建成功并生成一个全局唯一的XID;
- XID在微服务调用链路的上下文传播;
- RM向TC注册分支事务,将其纳入XID对应全局事务的管辖;
- TM向TC发起针对XID的全局提交或回滚决议;
- TC调度XID下管辖的全部分支事务完成提交或者回滚请求
三、Seata的部署
Seata的版本选择: Spring Cloud Alibaba与Spring Boot、Spring Cloud版本对应关系
本次使用:Seata 1.2.0
3.1 Seata Server端配置
官方配置文档:Seata部署指南
下载seata-server-1.2.0和seata-1.2.0源码
- seate-server下载: https://seata.io/zh-cn/blog/download.html
- seata-1.2.0源码下载: https://github.com/seata/seata/releases
3.1.1 修改配置文件
解压后,进入 conf
目录开始参数的配置。我们修改 file.conf
和 registry.conf
这两个文件。
1、进入conf文件夹,修改file.conf文件
2、修改registry.conf文件
- 如果config设置成了file,则不需要网上的设置nacos的配置
3.1.2 MySQL 数据库配置
我们先创建数据库seata(数据库要与file.conf中db设置那里对应),数据库的建表语句在README文件的server连接中
让后执行mysql.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_gmt_modified_status` (`gmt_modified`, `status`),
KEY `idx_transaction_id` (`transaction_id`)
) ENGINE = InnoDB
DEFAULT CHARSET = utf8;
-- 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 = InnoDB
DEFAULT CHARSET = utf8;
-- the table to store lock data
CREATE TABLE IF NOT EXISTS `lock_table`
(
`row_key` VARCHAR(128) NOT NULL,
`xid` VARCHAR(96),
`transaction_id` BIGINT,
`branch_id` BIGINT NOT NULL,
`resource_id` VARCHAR(256),
`table_name` VARCHAR(32),
`pk` VARCHAR(36),
`gmt_create` DATETIME,
`gmt_modified` DATETIME,
PRIMARY KEY (`row_key`),
KEY `idx_branch_id` (`branch_id`)
) ENGINE = InnoDB
DEFAULT CHARSET = utf8;
3.1.3 启动Seata Server端
3.2 Seata Client 客户端配置
3.2.1 业务前置准备
业务场景:用户购买商品的业务逻辑。整个业务逻辑由3个微服务提供支持:
用户A购买商品,调用 A服务
创建订单完成,调用 B服务
扣减库存,然后调用 C服务
扣减账户余额。每个服务内部的数据一致性由本地事务来保证,多个服务调用来完成业务,全局事务数据一致性则由 Seata 来保证。
-
订单服务A:根据采购需求创建订单。
-
仓储服务B:对给定的商品扣除仓储数量。
-
帐户服务C:从用户帐户中扣除余额。
**业务数据库准备:**配置三个业务分别对应各自的数据库。
- A服务 对应数据库:seata_order ;表:t_order
- B服务 对应数据库:seata_storage ;表:t_storage
- C服务 对应数据库:seata_account ;表:t_account
建表语句:
# 创建seata_order数据库
CREATE DATABASE seata_order;
# 创建t_order表
CREATE TABLE seata_order.t_order(
`id` BIGINT(11) NOT NULL AUTO_INCREMENT PRIMARY KEY,
`user_id` BIGINT(11) DEFAULT NULL COMMENT '用户id',
`product_id` BIGINT(11) DEFAULT NULL COMMENT '产品id',
`count` INT(11) DEFAULT NULL COMMENT '数量',
`money` DECIMAL(11,0) DEFAULT NULL COMMENT '金额',
`status` INT(1) DEFAULT NULL COMMENT '订单状态:0:创建中; 1:已完结'
) ENGINE=INNODB AUTO_INCREMENT=7 DEFAULT CHARSET=utf8;
# 创建seata_storage数据库
CREATE DATABASE seata_storage;
# 创建t_storage表
CREATE TABLE seata_storage.t_storage(
`id` BIGINT(11) NOT NULL AUTO_INCREMENT PRIMARY KEY,
`product_id` BIGINT(11) DEFAULT NULL COMMENT '产品id',
`total` INT(11) DEFAULT NULL COMMENT '总库存',
`used` INT(11) DEFAULT NULL COMMENT '已用库存',
`residue` INT(11) DEFAULT NULL COMMENT '剩余库存'
) ENGINE=INNODB AUTO_INCREMENT=2 DEFAULT CHARSET=utf8;
# 插入一条数据
INSERT INTO seata_storage.t_storage(`id`,`product_id`,`total`,`used`,`residue`)
VALUES('1','1','100','0','100');
# 创建seata_account数据库
CREATE DATABASE seata_account;
# 创建t_account表
CREATE TABLE seata_account.t_account(
`id` BIGINT(11) NOT NULL AUTO_INCREMENT PRIMARY KEY COMMENT 'id',
`user_id` BIGINT(11) DEFAULT NULL COMMENT '用户id',
`total` DECIMAL(10,0) DEFAULT NULL COMMENT '总额度',
`used` DECIMAL(10,0) DEFAULT NULL COMMENT '已用余额',
`residue` DECIMAL(10,0) DEFAULT '0' COMMENT '剩余可用额度'
) ENGINE=INNODB AUTO_INCREMENT=2 DEFAULT CHARSET=utf8;
# 插入一条数据
INSERT INTO seata_account.t_account(`id`,`user_id`,`total`,`used`,`residue`) VALUES('1','1','1000','0','1000');
3.2.2 创建undo_log表
按照上述3库分别建对应的回滚日志表,建表文件在README_ZH文件中的client中
undo_log表建表语句如下:
-- for AT mode you must to init this sql for you business database. the seata server not need it.
CREATE TABLE IF NOT EXISTS `undo_log`
(
`id` BIGINT(20) NOT NULL AUTO_INCREMENT COMMENT 'increment id',
`branch_id` BIGINT(20) NOT NULL COMMENT 'branch transaction id',
`xid` VARCHAR(100) NOT NULL COMMENT 'global transaction id',
`context` VARCHAR(128) NOT NULL COMMENT 'undo_log context,such as serialization',
`rollback_info` LONGBLOB NOT NULL COMMENT 'rollback info',
`log_status` INT(11) NOT NULL COMMENT '0:normal status,1:defense status',
`log_created` DATETIME NOT NULL COMMENT 'create datetime',
`log_modified` DATETIME NOT NULL COMMENT 'modify datetime',
PRIMARY KEY (`id`),
UNIQUE KEY `ux_undo_log` (`xid`, `branch_id`)
) ENGINE = InnoDB
AUTO_INCREMENT = 1
DEFAULT CHARSET = utf8 COMMENT ='AT transaction mode undo table';
完成图示:
以下配置以
seata-order-service2001
为例
项目结构:
3.2.3 Seata Client配置文件
配置文件的编写参考README_ZH文件中的client中:
1、file.conf,修改这一处
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 = 10000
# the tc client rpc request timeout
rpcTcRequestTimeout = 5000
#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.my_test_tx_group = "default"
#only support when registry.type=file, please don't set multiple addresses
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
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, 7z, 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 = "RandomLoadBalance"
virtualNodes = 10
log
exceptionRate = 100
tcc
fence
# tcc fence log table name
logTableName = tcc_fence_log
# tcc fence log clean period
cleanPeriod = 1h
2、registry.conf,修改这一处
registry
# file 、nacos 、eureka、redis、zk、consul、etcd3、sofa、custom
type = "nacos"
nacos
application = "seata-server"
serverAddr = "127.0.0.1:8848"
namespace = ""
username = ""
password = ""
##if use MSE Nacos with auth, mutex with username/password attribute
#accessKey = ""
#secretKey = ""
eureka
serviceUrl = "http://localhost:8761/eureka"
weight = "1"
redis
serverAddr = "localhost:6379"
db = "0"
password = ""
timeout = "0"
zk
serverAddr = "127.0.0.1:2181"
sessionTimeout = 6000
connectTimeout = 2000
username = ""
password = ""
consul
serverAddr = "127.0.0.1:8500"
aclToken = ""
etcd3
serverAddr = "http://localhost:2379"
sofa
serverAddr = "127.0.0.1:9603"
region = "DEFAULT_ZONE"
datacenter = "DefaultDataCenter"
group = "SEATA_GROUP"
addressWaitTime = "3000"
file
name = "file.conf"
custom
name = ""
config
# file、nacos 、apollo、zk、consul、etcd3、springCloudConfig、custom
type = "file"
nacos
serverAddr = "127.0.0.1:8848"
namespace = ""
group = "SEATA_GROUP"
username = ""
password = ""
##if use MSE Nacos with auth, mutex with username/password attribute
#accessKey = ""
#secretKey = ""
dataId = "seata.properties"
consul
serverAddr = "127.0.0.1:8500"
key = "seata.properties"
aclToken = ""
apollo
appId = "seata-server"
apolloMeta = "http://192.168.1.204:8801"
namespace = "application"
apolloAccesskeySecret = ""
zk
serverAddr = "127.0.0.1:2181"
sessionTimeout = 6000
connectTimeout = 2000
username = ""
password = ""
nodePath = "/seata/seata.properties"
etcd3
serverAddr = "http://localhost:2379"
key = "seata.properties"
file
name = "file.conf"
custom
name = ""
3.2.4 pom.xml文件
<dependencies>
<!--nacos-->
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
</dependency>
<!--seata-->
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-seata</artifactId>
<exclusions>
<exclusion>
<artifactId>seata-all</artifactId>
<groupId>io.seata</groupId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>io.seata</groupId>
<artifactId>seata-all</artifactId>
<version>1.2.0</version>
</dependency>
<!--feign-->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-openfeign</artifactId>
</dependency>
<!--web-actuator-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
<!--mysql-druid-->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.37</version>
</dependency>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid-spring-boot-starter</artifactId>
<version>1.1.10</version>
</dependency>
<dependency>
<groupId>org.mybatis.spring.boot</groupIspringcloudalibabaseata处理分布式事务及示例demo(代码片段)
创建undo_log表,此表为seata框架使用:CREATETABLE`undo_log`(`id`bigint(20)NOTNULLAUTO_INCREMENT,`branch_id`bigint(20)NOTNULL,`xid`varchar(100)NOTNULL,`context` 查看详情
springcloudalibabaseata分布式事务使用快速入门,nacos做seata的注册中心和配置中心
SpringCloudSeata分布式事务使用快速入门特点1、文档教程详细且提供完整源码及数据库脚本2、有配套全手敲代码的视频演示教程使用版本SpringCloudAlibaba2021.1Nacos1.4.1Seata1.3.0概念说明:本地事务及分布式事务本地事务1、在一个进... 查看详情
springcloudalibabaseata分布式事务使用快速入门,nacos做seata的注册中心和配置中心(代码片段)
SpringCloudSeata分布式事务使用快速入门特点1、文档教程详细且提供完整源码及数据库脚本2、有配套全手敲代码的视频演示教程使用版本SpringCloudAlibaba2021.1Nacos1.4.1Seata1.3.0概念说明:本地事务及分布式事务本地事务1、在一个进... 查看详情
springcloudalibabaseata分布式事务解决方案(代码片段)
SpringCloudAlibabaSeata分布式事务解决方案一、分布式事务问题二、Seata简介三、Seata的部署3.1SeataServer端配置3.1.1修改配置文件3.1.2MySQL数据库配置3.1.3启动SeataServer端3.2SeataClient客户端配置3.2.1业务前置准备3.2.2创建undo_log表3.2.3SeataClient... 查看详情
springcloudalibabaseata分布式事务(代码片段)
超详细的Java知识点路线图Seata简介在传统的单体项目中,我们使用@Transactional注解就能实现基本的ACID事务了。但是前提是:1)数据库支持事务(如:MySQL的innoDB引擎)2)所有业务都在同一个数据库... 查看详情
springcloudalibabaseata分布式事务使用快速入门,nacos做seata的注册中心和配置中心(代码片段)
SpringCloudSeata分布式事务使用快速入门特点1、文档教程详细且提供完整源码及数据库脚本2、有配套全手敲代码的视频演示教程使用版本SpringCloudAlibaba2021.1Nacos1.4.1Seata1.3.0概念说明:本地事务及分布式事务本地事务1、在一个进... 查看详情
springcloudalibabaseata集成(代码片段)
主项目链接:https://gitee.com/java_wxid/java_wxid项目架构及博文总结:点击:【使用SpringBoot快速构建应用】点击:【使用SpringCloudOpenFeign基于动态代理动态构造请求实现与其他系统进行交互】点击:【使用SpringCloudHy... 查看详情
seata:分布式事务(代码片段)
SpringCloudAlibabaSeata:分布式事务一、Seata简介1.Seata的由来随着互联网项目的发展,分布式架构的项目显示出了独特的独特的魅力。但是分布式事务问题在分布式架构项目中越显重要。2019年1月阿里巴巴团队发起了开源项目Fesca... 查看详情
springcloudalibabaseata集成(代码片段)
文章目录SeataServer部署:DB存储模式+Nacos(注册&配置中心)部署步骤一:下载安装包步骤二:建表(仅db模式)步骤三:修改store.mode步骤四:修改数据库连接步骤五:配置Nacos步骤六:启动SeataServerSeataCl... 查看详情
springcloud微服务架构(基础详解)(代码片段)
...acos集群与持久化SpringCloudAlibabaSentinel服务熔断降级、限流SpringCloudAlibabaSeata分布式事务框架微服务架构的概念微服务架构是一种架构模式,它提倡将单一的应用程序划分成一组小的服务,服务之间互相协 查看详情
4.抽样分布—卡方分布f分布t分布beta分布gamma分布——python实战
...统计量常用统计量次度统计量充分统计量2、什么是抽样分布3、卡方分布概率密度python代码实现性质非中心卡方分布4、t分布概率密度python代码实现性质5、F分布概率密度python代码实现性质6、样本分布7、其他类型分布Gamma分布族Be... 查看详情
常用的概率分布:二项式分布,贝塔分布,狄里克雷分布
知识点:伯努利分布、二项式分布、多项式分布、先验概率,后验概率,共轭分布、贝塔分布、贝塔-二项分布、负二项分布、狄里克雷分布,伽马函数、分布一,伯努利分布(bernoulidistribution)又叫做0-1分布,指一次随机试验,结... 查看详情
分布式(分布式事务/分布式协议/分布式id/分布式锁)
分布式事务/分布式协议一文说清各种分布式一致性协议_wh柒八九的博客-CSDN博客_分布式一致性协议分布式ID 美团(Leaf)分布式ID算法_wh柒八九的博客-CSDN博客_美团leaf算法 脑裂问题解决办法高可用集群的脑裂问题_wh柒八... 查看详情
抽样分布t分布
定义t分布设X~N(0,1),Y~ χ2(n),且X,Y相互独立,则称随机变量 服从自由度为n的t分布(学生氏分布)记为t~t(n),其概率密度为由于tn(x)是偶函数,其图形关于y轴对称。当n趋于无穷大时,t分布以标准正态... 查看详情
(0,1)分布(两点分布)
定义两点分布的期望和方差期望[EX=p]方差[DX=p(1-p)]注:证明见二项分布. 查看详情
正态分布与偏态分布的概念
正态分布又称高斯分布,是一种最重要的连续型分布。它是以均数为中心呈对称的钟型分布。早在1733年a.demoivre首先提出这种分布的方程,他以此作为二项分布的极限形式。至19世纪初期,德国数学家c.f.gauss与法国数学家p.s.delapla... 查看详情
伯努利分布二项分布多项分布beta分布dirichlet分布
1.伯努利分布伯努利分布(Bernoullidistribution)又名两点分布或0-1分布,介绍伯努利分布前首先需要引入伯努利试验(Bernoullitrial)。伯努利试验是只有两种可能结果的单次随机试验,即对于一个随机变量X而言: 伯努利试验都可... 查看详情
二项分布,多项分布,以及与之对应的beta分布和狄利克雷分布
1.二项分布与beta分布对应 2.多项分布与狄利克雷分布对应3.二项分布是什么?n次bernuli试验服从二项分布 二项分布是N次重复bernuli试验结果的分布。bernuli实验是什么?做一次抛硬币实验,该试验结果只有2种情况,x=1,... 查看详情