分布式事务Seata

简介: 本章节深入探讨分布式事务问题,涵盖CAP定理与BASE理论,重点学习Seata框架的XA、AT、TCC及SAGA四种事务模式,掌握跨服务事务一致性解决方案,并实践高可用部署架构。

在分布式架构系统中,服务不止一个,一个完整的业务链路肯定也不止调用一个服务,此时每个服务都有自己的数据库增删改查,而每一个写操作对应一个本地事务。如果想要确保全部的业务状态一致,也就意味着需要所有的本地事务状态一致,这在我们之前的学习中肯定是不具备的,如何做到跨服务、跨数据源的事务一致性将是本章节的重点学习内容。

0.学习目标
了解分布式事务
了解CAP定理和BASE理论
能自己搭建Seata的TC服务并与微服务集成
理解XA模式原理并利用XA解决分布式事务
理解AT模式原理并利用AT解决分布式事务
理解TCC模式原理并利用TCC解决分布式事务
理解各种模式的优缺点
能部署Seata的异地高可用容灾架构
1.分布式事务问题
1.1.本地事务
本地事务,也就是传统的单机事务。在传统数据库事务中,必须要满足四个原则:

一致性

原子性

要保证数据库内部完整性约束,声明

事务中的所有操作,要么全部成功,

C

要么全部失败

性约束

D

持久性

隔离性

对同一资源操作的事务不能同时发生

对数据库做的一切修改将永久保存,

不管是否出现故障


1.2.分布式事务
分布式事务,就是指不是在单个服务或单个数据库架构下,产生的事务,例如:
跨数据源的分布式事务
跨服务的分布式事务
综合情况
在数据库水平拆分、服务垂直拆分之后,一个业务操作通常要跨多个数据库、服务才能完成。例如电商行业中比较常见的下单付款案例,包括下面几个行为:
创建新订单
扣减商品库存
从用户账户余额扣除金额
完成上面的操作需要访问三个不同的微服务和三个不同的数据库。

SSINT

订单服务

账户服务

库存服务

1.创建订单

3.扣减商品库存I

2.扣减余额

DB

DB

DB


订单的创建、库存的扣减、账户扣款在每一个服务和数据库内是一个本地事务,可以保证ACID原则。
但是当我们把三件事情看做一个"业务",要满足保证“业务”的原子性,要么所有操作全部成功,要么全部失败,不允许出现部分成功部分失败的现象,这就是分布式系统下的事务了。此时ACID难以满足,这是分布式事务要解决的问题
1.3.演示分布式事务问题
我们通过一个案例来演示分布式事务的问题:
1)创建数据库,名为seata_demo,然后导入SQL文件:
2)导入课前资料提供的微服务:

seata-demo.zip(25 KB)
微服务结构中:
seata-demo:父工程,负责管理项目依赖
account-service:账户服务,负责管理用户的资金账户。提供扣减余额的接口
storage-service:库存服务,负责管理商品库存。提供扣减库存的接口
order-service:订单服务,负责管理订单。创建订单时,需要调用account-service和storage-service
3)启动nacos、所有微服务
4)测试下单功能,发出Post请求:
请求如下:
如图:
请求方式:POST
请求地址:http://localhost:8082/order?userId=user202103032042012&commodityCode=100202003032041&count=20&money=200

SEATA-DEMO接口/创建订单

SAVE

HTTP://0CAHOST-8082/ORDERFUSERLD-USER2021030320128COMMODITYCODE-10020020030320418COUNT-208MONEY

POST

PRE-REQUEST SCRIPT

BODY

SETTINGS

HEADERS (8)

PARAMS

AUTHORIZATION

TESTS

QUERY PARAMS

DESCRIPTION

VALUE

KEY

用户ID

USER202103032042012

USERLD

商品编号

100202003032041

COMMODITYCODE

商品数量

20

COUNT

总金额

200

MONEY

DESCRIPTION

KEY

VALUE


测试发现,当库存不足时,如果余额已经扣减,并不会回滚,出现了分布式事务问题。

<FILTER CRITERIA>

MUSER_ID

ID

MONEY

1

USER202103032042012

600

R URITERIA>

钱扣了

ID

P

MONEY

USER

1

USER202103032042012

800

<FILTER CRITERIA>

用 COUNT

COMMODITY_CODE

ID

100202003032041

8

1

库存没有减少

I COUNT

D COMMODITY_CODE

1

100202003032041

8


2.理论基础
解决分布式事务问题,需要一些分布式系统的基础知识作为理论指导。
2.1.CAP定理
1998年,加州大学的计算机科学家 Eric Brewer 提出,分布式系统有三个指标。
Consistency(一致性)
Availability(可用性)
Partition tolerance (分区容错性)
它们的第一个字母分别是 C、A、P。Eric Brewer 说,这三个指标不可能同时做到。这个结论就叫做 CAP 定理。
2.1.1.一致性
Consistency(一致性):用户访问分布式系统中的任意节点,得到的数据必须一致。
比如现在包含两个节点,其中的初始数据是一致的:

DATA:VO

DATA:VO

NODE02

NODE01


当我们修改其中一个节点的数据时,两者的数据产生了差异:

DATA:V1

DATA:VO

NODE02

NODE01


要想保住一致性,就必须实现node01 到 node02的数据 同步:

DATA:V1

DATA:V1

NODE02

NODE01

数据同步


2.1.2.可用性
Availability (可用性):用户访问集群中的任意健康节点,必须能得到响应,而不是超时或拒绝。如图,有三个节点的集群,访问任何一个都可以及时得到响应:

DATA:VO

DATA:VO

DATA:VO

数据同步

数据同步

NODE01

NODE02

NODE03


当有部分节点因为网络故障或其它原因无法访问时,代表节点不可用:

DATA:VO

DATA:VO

DATA:VO

数据同步

数据同步

NODE01

NODE03

NODE02

阻塞或拒绝


2.1.3.分区容错
Partition(分区):因为网络故障或其它原因导致分布式系统中的部分节点与其它节点失去连接,形成独立分区。

DATA:VO

DATA:VO

DATA:VO

GB

数据同步

数据同步

NODE01

NODE03

NODE02


Tolerance(容错):在集群出现分区时,整个系统也要持续对外提供服务
2.1.4.矛盾
在分布式系统中,系统间的网络不能100%保证健康,一定会有故障的时候,而服务又必须对外保证服务。因此Partition Tolerance不可避免。当节点接收到新的数据变更时,就会出现问题了:
如果此时要保证一致性,就必须等待网络恢复,完成数据同步后,整个集群才对外提供服务,服务处于阻塞状态,不可用。
如果此时要保证可用性,就不能等待网络恢复,那node01、node02与node03之间就会出现数据不一致。
也就是说,在P一定会出现的情况下,A和C之间只能实现一个。
2.2.BASE理论
BASE理论是对CAP的一种解决思路,包含三个思想:
Basically Available (基本可用):分布式系统在出现故障时,允许损失部分可用性,即保证核心可用。
Soft State(软状态):在一定时间内,允许出现中间状态,比如临时的不一致状态。
Eventually Consistent(最终一致性):虽然无法保证强一致性,但是在软状态结束后,最终达到数据一致。
2.3.解决分布式事务的思路
分布式事务最大的问题是各个子事务的一致性问题,因此可以借鉴CAP定理和BASE理论,有两种解决思路:
AP模式:各子事务分别执行和提交,允许出现结果不一致,然后采用弥补措施恢复数据即可,实现最终一致。
CP模式:各个子事务执行后互相等待,同时提交,同时回滚,达成强一致。但事务等待过程中,处于弱可用状态。
但不管是哪一种模式,都需要在子系统事务之间互相通讯,协调事务状态,也就是需要一个事务协调者(TC):

$

S51:

订单服务

下单成功

事务协

账户服务

调者

扣款成功

库存服务

库存不足


这里的子系统事务,称为分支事务;有关联的各个分支事务在一起称为全局事务。
3.初识Seata
Seata是 2019 年 1 月份蚂蚁金服和阿里巴巴共同开源的分布式事务解决方案。致力于提供高性能和简单易用的分布式事务服务,为用户打造一站式的分布式解决方案。官网地址:http://seata.io/,其中的文档、播客中提供了大量的使用说明、源码分析。

下载

文档

博客

开发者

EN

社区

首页

暑期2021


3.1.Seata的架构
Seata事务管理中有三个重要的角色:
TC (Transaction Coordinator) - 事务协调者:维护全局和分支事务的状态,协调全局事务提交或回滚。
TM (Transaction Manager) - 事务管理器:定义全局事务的范围、开始全局事务、提交或回滚全局事务。
RM (Resource Manager) - 资源管理器:管理分支事务处理的资源,与TC交谈以注册分支事务和报告分支事务的状态,并驱动分支事务提交或回滚。
整体的架构如图:

开启全局事务

分支事务

微服务

RM

全局事务

分支事务的注册,报告

TC

TM

分支事务

微服务

RM

提交,回滚全局事务


Seata基于上述架构提供了四种不同的分布式事务解决方案:
XA模式:强一致性分阶段事务模式,牺牲了一定的可用性,无业务侵入
TCC模式:最终一致的分阶段事务模式,有业务侵入
AT模式:最终一致的分阶段事务模式,无业务侵入,也是Seata的默认模式
SAGA模式:长事务模式,有业务侵入
无论哪种方案,都离不开TC,也就是事务的协调者。
3.2.部署TC服务
参考:

Seata的部署和集成


3.3.微服务集成Seata
我们以order-service为例来演示。
3.3.1.引入依赖
首先,在order-service中引入依赖:
3.3.2.配置TC地址
在order-service中的application.yml中,配置TC服务信息,通过注册中心nacos,结合服务名称获取TC地址:
微服务如何根据这些配置寻找TC的地址呢?我们知道注册到Nacos中的微服务,确定一个具体实例需要四个信息:
namespace:命名空间
group:分组
application:服务名
cluster:集群名
以上四个信息,在刚才的yaml文件中都能找到:

SEATA:

NAMESPACE

REGISTRY:#TC服务地址

#参考TC服务自己的REGISTRY.CONF中的配置,

# 包括:地址,NAMESPACE,GROUP,APPLICATION-NAME.

CLUSTER

TYPE:NACOS

GROUP

# TC

NACOS:

SERVER-ADDR:127.0.0.1:8848

NAMESPACE:"""

GROUP:DEFAULT_GROUP

SERVICE

SEATA-TC-SERVER # TC服务在NACOS中的服务名称

APPLICATION:

事务组,根据这个获取TC服务的CLUSTER名称

TX-SERVICE-GROUP:

SEATA-DEMO

SERVICE:

事务组与TC服务CLUSTER的映射关系

#

VGROUP-MAPPING:

CLUSTER

CLUSTER

SH

SEATA-DEMO


namespace为空,就是默认的public
结合起来,TC服务的信息就是:public@DEFAULT_GROUP@seata-tc-server@GZ,这样就能确定TC服务集群了。然后就可以去Nacos拉取对应的实例信息了。
3.3.3.其它服务
其它两个微服务也都参考order-service的步骤来做,完全一样。
4.动手实践
下面我们就一起学习下Seata中的四种不同的事务模式。
4.1.XA模式
XA 规范 是 X/Open 组织定义的分布式事务处理(DTP,Distributed Transaction Processing)标准,XA 规范 描述了全局的TM与局部的RM之间的接口,几乎所有主流的数据库都对 XA 规范 提供了支持。
4.1.1.两阶段提交
XA是规范,目前主流数据库都实现了这种规范,实现的原理都是基于两阶段提交。
正常情况:

2.1.提交(COMMIT)

1.1.准备(PREPARE)

RM

RM

2.2.已提交(COMMITED)

者(READY)

1.2.就绪

事务

事务

协调

协调

1.1.准备(PREPARE)

2.1.提交(COMMIT)

RM

RM

2.2.已提交(COMMITED)

1.2.就绪(READY)

第二阶段

第一阶段


异常情况:

2.1.回滚(FALLBACK)

1.1.准备(PREPARE)

RM

RM

1.2.就绪(READY)

2.2.已回滚

事务

事务

协调

协调

1.1.准备(PREPARE)

RM

RM

1.2.失败(FAIL)

第二阶段

第一阶段


一阶段:
事务协调者通知每个事物参与者执行本地事务
本地事务执行完成后报告事务执行状态给事务协调者,此时事务不提交,继续持有数据库锁
二阶段:
事务协调者基于一阶段的报告来判断下一步操作
如果一阶段都成功,则通知所有事务参与者,提交事务
如果一阶段任意一个参与者失败,则通知所有事务参与者回滚事务
4.1.2.Seata的XA模型
Seata对原始的XA模式做了简单的封装和改造,以适应自己的事务模型,基本架构如图:

1.1.开启全局事务

1.3.注册分支事务

.执行业务SQL

1.5.报告事务状态

RM

1.2调用分支

2.3.提交/回滚

微服务

TC

TM

1.3.注册分支事务

1.4.执行业务SQL

2.2.

1.5.报告事务状态

RM

检查

1.2调用分支

分支

事务

2.3.提交/回滚

微服务

状态

2.1.提交,回滚全局事务


RM一阶段的工作:
① 注册分支事务到TC
② 执行分支业务sql但不提交
③ 报告执行状态到TC
TC二阶段的工作:
TC检测各分支事务执行状态a.如果都成功,通知所有RM提交事务b.如果有失败,通知所有RM回滚事务
RM二阶段的工作:
接收TC指令,提交或回滚事务
4.1.3.优缺点
XA模式的优点是什么?
事务的强一致性,满足ACID原则。
常用数据库都支持,实现简单,并且没有代码侵入
XA模式的缺点是什么?
因为一阶段需要锁定数据库资源,等待二阶段结束才释放,性能较差
依赖关系型数据库实现事务
4.1.4.实现XA模式
Seata的starter已经完成了XA模式的自动装配,实现非常简单,步骤如下:
1)修改application.yml文件(每个参与事务的微服务),开启XA模式:
2)给发起全局事务的入口方法添加@GlobalTransactional注解:
本例中是OrderServiceImpl中的create方法.

ORDERSERVICELMPL.JAVA

@OVERRIDE

30

@GLOBALTRANSACTIONAL

31

PUBLIC LONG

32

G CREATE(ORDER ORDER) {

/创建订单

33

ORDERMAPPER.INSERT(ORDER);

34

35

TRY{

1/扣用户余额

36

ACCOUNTCLIENT.DEDUCT(ORDER.GETUSERID(), ORDER.GETMONEY());

37

1/扣库存

38

STORAGECLIENT.DEDUCT(ORDER.GETCOMMODITYCODE(), ORDER.GETCOUNT();

39

40

(FEIGNEXCEPTIONE)

CATCH (R

41

LOG.ERROR("下单失败,原因:{}",E.CONTENTUTF8(),E);

42

(E.CONTENTUTF8(),E);

THROW NEW RUNTIMEEXCEPTION(E.

43

44

45

RETURN ORDER.GETID();

46

47


3)重启服务并测试
重启order-service,再次测试,发现无论怎样,三个微服务都能成功回滚。
4.2.AT模式
AT模式同样是分阶段提交的事务模型,不过缺弥补了XA模型中资源锁定周期过长的缺陷。
4.2.1.Seata的AT模型
基本流程图:

1.1.开启全局事务

1.3.注册分支事务

1.2调用分支

1.4.执行SQL并提交

1.5.报告事务状态

记录更新前后快照

RM

UNDO

10G

2.3.提交

2.4.删除LOG

回滚

2.4.恢复LOG数据

TC

TM

1.3.注册分支事务

1.2调用分支

1.4.执行SQL并提交

1.5.报告事务状态

2.2.

记录更新前后快照

UNDO

RM

检查

LOG

分支

2.3.提交

2.4.删除LOG

事务

2.3.回滚

2.4.恢复LOG数据

状态

-

-

-

2.1.提交,回滚全局事务


阶段一RM的工作:
注册分支事务
记录undo-log(数据快照)
执行业务sql并提交
报告事务状态
阶段二提交时RM的工作:
删除undo-log即可
阶段二回滚时RM的工作:
根据undo-log恢复数据到更新前
4.2.2.流程梳理
我们用一个真实的业务来梳理下AT模式的原理。
比如,现在有一个数据库表,记录用户余额:

id

money

1

100

其中一个分支业务要执行的SQL为:
AT模式下,当前分支事务执行流程如下:
一阶段:
1)TM发起并注册全局事务到TC
2)TM调用分支事务
3)分支事务准备执行业务SQL
4)RM拦截业务SQL,根据where条件查询原始数据,形成快照。
5)RM执行业务SQL,提交本地事务,释放数据库锁。此时 money = 90
6)RM报告本地事务状态给TC
二阶段:
1)TM通知TC事务结束
2)TC检查分支事务状态
a)如果都成功,则立即删除快照
b)如果有分支事务失败,需要回滚。读取快照数据({"id": 1, "money": 100}),将快照恢复到数据库。此时数据库再次恢复为100
流程图:

S

注册分支事务

阶段

记录快照

执行业务SQL

提交,报告事务状态

是否可以

提交

阶段二

删除快照

读取快照,恢复数据

E


4.2.3.AT与XA的区别
简述AT模式与XA模式最大的区别是什么?
XA模式一阶段不提交事务,锁定资源;AT模式一阶段直接提交,不锁定资源。
XA模式依赖数据库机制实现回滚;AT模式利用数据快照实现数据回滚。
XA模式强一致;AT模式最终一致
4.2.4.脏写问题
在多线程并发访问AT模式的分布式事务时,有可能出现脏写问题,如图:

AT模式的脏写问题

ID

MONEY

1

100

事务2

事务1

UPDATE ACCOUNT SET MONEY : MONEY - 10 WHERE ID : 1

1.1.获取DB锁,保存快照

{"ID":1,"MONEY":100}

1.2.执行业务SQL

SET MONEY 2 90

1.3.提交事务,释放DB锁此时数据库为90

1.1.获取DB锁,保存快照

{"ID":1,"MONEY":90]

口.

1.2.执行业务SQL

SET MONEY 80

1.3.提交事务,释放DB锁

此时数据库为80

{"ID":1,"MONEY":100}

此时数据库为80,如果按照快照恢复为100,

就丢失了一次更新,出现脏写了.

2.1.获取DB锁,根据快照恢复数据


解决思路就是引入了全局锁的概念。在释放DB锁之前,先拿到全局锁。避免同一时刻有另外一个事务来操作当前数据。

AT模式的写隔离

ID

MONEY

100

1

事务2

事务1

UPDATE ACCOUNT SET MONEY - MONEY - 10 WHERE ID - 1

1.1.获取DB锁,保存快照

{"ID":1,"MONEY":100]

1.2.执行业务SQL

全局锁:由TC记录当前正在操作某行数据的事务,

获取全局锁

SET MONEY - 90

该事务持有全局锁,具备执行权.

1.3.提交事务,释放DB锁

TABLE PK

XID

此时数据库为90

全局锁被事务1持有

事务1

1

ACCOUNT

1.1.获取DB锁,保存快照

{"ID":1,"MONEY":90}

1.2.执行业务SQL

获取全局锁

SET MONEY  80

等待DB锁

重试,默认30次,

间隔10毫秒

获取全局锁失败

{"ID":1,"MONEY":100}

1.4.任务超时,

事务回滚.

回滚并释放DB锁

数据库依然是90

因为事务2没有成功,这里回滚就不会有影响

2.1.获取DB锁,根据快照恢复数据


4.2.5.优缺点
AT模式的优点:
一阶段完成直接提交事务,释放数据库资源,性能比较好
利用全局锁实现读写隔离
没有代码侵入,框架自动完成回滚和提交
AT模式的缺点:
两阶段之间属于软状态,属于最终一致
框架的快照功能会影响性能,但比XA模式要好很多
4.2.6.实现AT模式
AT模式中的快照生成、回滚等动作都是由框架自动完成,没有任何代码侵入,因此实现非常简单。
只不过,AT模式需要一个表来记录全局锁、另一张表来记录数据快照undo_log。
1)导入数据库表,记录全局锁
其中lock_table、distributed_lock导入到TC服务关联的数据库(seata),undo_log表导入到微服务关联的数据库(seata_demo):
2)修改application.yml文件,将事务模式修改为AT模式即可:
3)重启服务并测试
4.3.TCC模式
TCC模式与AT模式非常相似,每阶段都是独立事务,不同的是TCC通过人工编码来实现数据恢复。需要实现三个方法:
Try:资源的检测和预留;
Confirm:完成资源操作业务;要求 Try 成功 Confirm 一定要能成功。
Cancel:预留资源释放,可以理解为try的反向操作。
4.3.1.流程分析
举例,一个扣减用户余额的业务。假设账户A原来余额是100,需要余额扣减30元。
阶段一( Try ):检查余额是否充足,如果充足则冻结金额增加30元,可用余额扣除30
初始余额:

可用余额

R

100


余额充足,可以冻结:

冻结金额

可用余额

30

100


此时,总金额 = 冻结金额 + 可用金额,数量依然是100不变。事务直接提交无需等待其它事务。
阶段二(Confirm):假如要提交(Confirm),则冻结金额扣减30
确认可以提交,不过之前可用金额已经扣减过了,这里只要清除冻结金额就好了:

可用余额

70

R


此时,总金额 = 冻结金额 + 可用金额 = 0 + 70  = 70元
阶段二(Canncel):如果要回滚(Cancel),则冻结金额扣减30,可用余额增加30
需要回滚,那么就要释放冻结金额,恢复可用金额:

可用余额

100


4.3.2.Seata的TCC模型
Seata中的TCC模型依然延续之前的事务架构,如图:

1.1.开启全局事务

1.3.注册分支事务

1.2调用分支

1.4.资源预留(TRY)

1.5.报告事务状态

RM

2.4.CONFIRM

2.3.提交

2.4.CANCEL

2.3.回滚

TC

TM

1.3.注册分支事务

1.2调用分支

.资源预留(TRY)

1.5.报告事务状态

2.2.

RM

检查

2.4.CONFIRM

分支

2.3.提交

事务

2.4.CANCEL

状态

2.3.回滚

2.1.提交,回滚全局事务


4.3.3.优缺点
TCC模式的每个阶段是做什么的?
Try:资源检查和预留
Confirm:业务执行和提交
Cancel:预留资源的释放
TCC的优点是什么?
一阶段完成直接提交事务,释放数据库资源,性能好
相比AT模型,无需生成快照,无需使用全局锁,性能最强
不依赖数据库事务,而是依赖补偿操作,可以用于非事务型数据库
TCC的缺点是什么?
有代码侵入,需要人为编写try、Confirm和Cancel接口,太麻烦
软状态,事务是最终一致
需要考虑Confirm和Cancel的失败情况,做好幂等处理
4.3.4.事务悬挂和空回滚
1)空回滚
当某分支事务的try阶段阻塞时,可能导致全局事务超时而触发二阶段的cancel操作。在未执行try操作时先执行了cancel操作,这时cancel不能做回滚,就是空回滚。
如图:

1.1.开启全局事务

-

-

1.3.注册分支事务

1.2调用分支

1.4.锁定资源(TRY)

1.5.报告事务状态

RM

2.4.CANCEL

2.3.回滚

TC

TM

阻塞

1.2调用分支

因为没有执行TRY

RM

检查

CANCEL只能空回滚

分支

2.4.CANCEL

事务

2.3.回滚

状态

2.1.超时错误,回滚全局事务


执行cancel操作时,应当判断try是否已经执行,如果尚未执行,则应该空回滚。
2)业务悬挂
对于已经空回滚的业务,之前被阻塞的try操作恢复,继续执行try,就永远不可能confirm或cancel ,事务一直处于中间状态,这就是业务悬挂。
执行try操作时,应当判断cancel是否已经执行过了,如果已经执行,应当阻止空回滚后的try操作,避免悬挂
4.3.5.实现TCC模式
解决空回滚和业务悬挂问题,必须要记录当前事务状态,是在try、还是cancel?
1)思路分析
这里我们定义一张表;在 seata_demo数据库中创建如下表:
其中:
xid:是全局事务id
freeze_money:用来记录用户冻结金额
state:用来记录事务状态
那此时,我们的业务该怎么做呢?
Try业务:
记录冻结金额和事务状态到account_freeze表
扣减account表可用金额
Confirm业务
根据xid删除account_freeze表的冻结记录
Cancel业务
修改account_freeze表,冻结金额为0,state为2
修改account表,恢复可用金额
如何判断是否空回滚?
cancel业务中,根据xid查询account_freeze,如果为null则说明try还没做,需要空回滚
如何避免业务悬挂?
try业务中,根据xid查询account_freeze ,如果已经存在则证明Cancel已经执行,拒绝执行try业务
接下来,我们改造account-service,利用TCC实现余额扣减功能。
2)声明TCC接口
TCC的Try、Confirm、Cancel方法都需要在接口中基于注解来声明,
我们在account-service项目中的cn.itcast.account.service包中新建一个接口,声明TCC三个接口:
3)编写实现类
在account-service服务中的cn.itcast.account.service.impl包下新建一个类,实现TCC业务:

改造 src/main/java/cn/itcast/account/web/AccountController.java 如下:

@RESTCONTROLLER

@REQUESTMAPPING()V"ACCO

"ACCOUNT")

PUBLIC CLASS ACCOUNTCONTROLLER (

@AUTOWIRED

PRIVATE ACCOUNTTCCBERVICE ACCOUNTSERVICE;

@PUTMAPPING(OY"/FUSERID}/{MONEY}")

PUBLIC RESPONSESNTITY(YOID) DEDUCT(EPATHVERIABLE("2SERID") STRING USERID, GPATHVARIABLE("MONEYY) ( 2

INTEGER MONEY){

ACCOUNTSERVICE.DEDUCT(USERID, MONEY);

RETURN RESPONSEENTITY.NOCONTENT().BUILD();


4.4.SAGA模式
Saga 模式是 Seata 即将开源的长事务解决方案,将由蚂蚁金服主要贡献。其理论基础是Hector & Kenneth  在1987年发表的论文Sagas
Seata官网对于Saga的指南:https://seata.io/zh-cn/docs/user/saga.html
4.4.1.原理
在 Saga 模式下,分布式事务内有多个参与者,每一个参与者都是一个冲正补偿服务,需要用户根据业务场景实现其正向操作和逆向回滚操作。
分布式事务执行过程中,依次执行各参与者的正向操作,如果所有正向操作均执行成功,那么分布式事务提交。如果任何一个正向操作执行失败,那么分布式事务会去退回去执行前面各参与者的逆向回滚操作,回滚已提交的参与者,使分布式事务回到初始状态。

COMPENSATING TRANSACTIONS

NORMAL TRANSACTIONS

T1

C1

C2

T2

C3

T3

FAILS

TN


Saga也分为两个阶段:
一阶段:直接提交本地事务
二阶段:成功则什么都不做;失败则通过编写补偿业务来回滚
4.4.2.优缺点
优点:
事务参与者可以基于事件驱动实现异步调用,吞吐高
一阶段直接提交事务,无锁,性能好
不用编写TCC中的三个阶段,实现简单
缺点:
软状态持续时间不确定,时效性差
没有锁,没有事务隔离,会有脏写
4.5.四种模式对比
我们从以下几个方面来对比四种实现:
一致性:能否保证事务的一致性?强一致还是最终一致?
隔离性:事务之间的隔离性如何?
代码侵入:是否需要对业务代码改造?
性能:有无性能损耗?
场景:常见的业务场景
如图:

TCC

AT

XA

SAGA

强一致

弱一致

一致性

最终一致

弱一致

基于全局锁隔离

隔离性

完全隔离

基于资源预留隔离

无隔离

代码侵入

有,要编写状态机和补偿业务

有,要编写三个接口

非常好

性能

非常好

业务流程长,业务流程多

基于关系型数据库的

对性能要求较高的事务.

参与者包含其它公司或遗留

对一致性,隔离性

大多数分布式事务场

有非关系型数据库要参

场景

系统服务,无法提供TCC

有高要求的业务

与的事务.

景都可以

模式要求的三个接口


5.高可用
Seata的TC服务作为分布式事务核心,一定要保证集群的高可用性。
5.1.高可用架构模型
搭建TC服务集群非常简单,启动多个TC服务,注册到nacos即可。
但集群并不能确保100%安全,万一集群所在机房故障怎么办?所以如果要求较高,一般都会做异地多机房容灾。
比如一个TC集群在广州,另一个TC集群在杭州:

SERVICE:SEATA-TC-SERVER

CLUSTER:GZ

CLUSTER:HZ

TC

TC

TC

SERVER2

SERVERI

SERVER3

SERVER4

SERVICE:

VGROUP-MAPPING:

SEATA-DEMO:GZ

TX-SERVICE-QROUP:SEATA-DEMO

STORAGE-SERVICE

ORDER-SERVICE

ACCOUNT-SERVICE


微服务基于事务组(tx-service-group)与TC集群的映射关系,来查找当前应该使用哪个TC集群。当GZ集群故障时,只需要将vgroup-mapping中的映射关系改成HZ。则所有微服务就会切换到HZ的TC集群了。
5.2.实现高可用
具体实现请参考:《seata的部署和集成.md》


相关文章
|
1天前
|
数据采集 人工智能 安全
|
11天前
|
云安全 监控 安全
|
2天前
|
自然语言处理 API
万相 Wan2.6 全新升级发布!人人都能当导演的时代来了
通义万相2.6全新升级,支持文生图、图生视频、文生视频,打造电影级创作体验。智能分镜、角色扮演、音画同步,让创意一键成片,大众也能轻松制作高质量短视频。
938 150
|
2天前
|
编解码 人工智能 机器人
通义万相2.6,模型使用指南
智能分镜 | 多镜头叙事 | 支持15秒视频生成 | 高品质声音生成 | 多人稳定对话
|
16天前
|
机器学习/深度学习 人工智能 自然语言处理
Z-Image:冲击体验上限的下一代图像生成模型
通义实验室推出全新文生图模型Z-Image,以6B参数实现“快、稳、轻、准”突破。Turbo版本仅需8步亚秒级生成,支持16GB显存设备,中英双语理解与文字渲染尤为出色,真实感和美学表现媲美国际顶尖模型,被誉为“最值得关注的开源生图模型之一”。
1662 8
|
7天前
|
人工智能 自然语言处理 API
一句话生成拓扑图!AI+Draw.io 封神开源组合,工具让你的效率爆炸
一句话生成拓扑图!next-ai-draw-io 结合 AI 与 Draw.io,通过自然语言秒出架构图,支持私有部署、免费大模型接口,彻底解放生产力,绘图效率直接爆炸。
617 152
|
9天前
|
人工智能 安全 前端开发
AgentScope Java v1.0 发布,让 Java 开发者轻松构建企业级 Agentic 应用
AgentScope 重磅发布 Java 版本,拥抱企业开发主流技术栈。
587 15
|
9天前
|
人工智能 自然语言处理 API
Next AI Draw.io:当AI遇见Draw.io图表绘制
Next AI Draw.io 是一款融合AI与图表绘制的开源工具,基于Next.js实现,支持自然语言生成架构图、流程图等专业图表。集成多款主流大模型,提供智能绘图、图像识别优化、版本管理等功能,部署简单,安全可控,助力技术文档与系统设计高效创作。
672 151