网站备案和服务器备案,中国建设银行个人网上登录入口,wordpress 手机商城,wordpress禁止截图阶段八#xff1a;服务框架高级#xff08;第二章#xff1a;分布式事务#xff09;Day-分布式事务0.学习目标1.分布式事务问题1.1.本地事务1.2.分布式事务1.3.演示分布式事务问题2.理论基础2.1.CAP定理2.1.1.一致性2.1.2.可用性2.1.3.分区容错2.1.4.矛盾2.2.BASE理论2.3.解…
阶段八服务框架高级第二章分布式事务Day-分布式事务0.学习目标1.分布式事务问题1.1.本地事务1.2.分布式事务1.3.演示分布式事务问题2.理论基础2.1.CAP定理2.1.1.一致性2.1.2.可用性2.1.3.分区容错2.1.4.矛盾2.2.BASE理论2.3.解决分布式事务的思路3.初识Seata3.1.Seata的架构 【理解】3.2.部署TC服务 【重要不需要背过参照文档就可以】3.3.微服务集成Seata 【重要】3.3.1.引入依赖3.3.2.配置TC地址3.3.3.其它服务3.3.4.小结4.动手实践4.1.XA模式 【重要用的少】4.1.1.两阶段提交4.1.2.Seata的XA模型 【理解即可】4.1.3.优缺点4.1.4.实现XA模式 【重要】4.2.AT模式 【重要重要】4.2.1.Seata的AT模型 【理解】4.2.2.流程梳理4.2.3.AT与XA的区别4.2.4.脏写问题 【理解】4.2.5.优缺点4.2.6.实现AT模式 【重要】4.3.TCC模式 【重要重要】4.3.1.流程分析 【理解】4.3.2.Seata的TCC模型 【理解】4.3.3.优缺点4.3.4.事务悬挂和空回滚 【重要】1空回滚2业务悬挂4.3.5.实现TCC模式 【重要】1思路分析2声明TCC接口2编写实体类2编写mapper操作数据表3编写实现类 不全需要看代码补全4.4.SAGA模式 【没怎么说】4.4.1.原理4.4.2.优缺点4.5.四种模式对比5.高可用 【重要】5.1.高可用架构模型5.2.实现高可用Day-分布式事务
0.学习目标 1.分布式事务问题
1.1.本地事务
本地事务也就是传统的单机事务。在传统数据库事务中必须要满足四个原则
1.2.分布式事务 分布式事务:在分布式系统下一个业务跨越多个服务或数据源每个服务都是一个分支事务要保证所有分支事务最终状态一致这样的事务就是分布式事务。 分布式事务就是指不是在单个服务或单个数据库架构下产生的事务例如
跨数据源的分布式事务跨服务的分布式事务综合情况 在数据库水平拆分、服务垂直拆分之后一个业务操作通常要跨多个数据库、服务才能完成。例如电商行业中比较常见的下单付款案例包括下面几个行为
创建新订单扣减商品库存从用户账户余额扣除金额
完成上面的操作需要访问三个不同的微服务和三个不同的数据库。 订单的创建、库存的扣减、账户扣款在每一个服务和数据库内是一个本地事务可以保证ACID原则。 但是当我们把三件事情看做一个业务要满足保证“业务”的原子性要么所有操作全部成功要么全部失败不允许出现部分成功部分失败的现象这就是分布式系统下的事务了。 此时ACID难以满足这是分布式事务要解决的问题
1.3.演示分布式事务问题
我们通过一个案例来演示分布式事务的问题
1创建数据库名为seata_demo然后导入课前资料提供的SQL文件 2导入课前资料提供的微服务 微服务结构如下 其中
seata-demo父工程负责管理项目依赖
account-service账户服务负责管理用户的资金账户。提供扣减余额的接口storage-service库存服务负责管理商品库存。提供扣减库存的接口order-service订单服务负责管理订单。创建订单时需要调用account-service和storage-service
3启动nacos、所有微服务
4测试下单功能发出Post请求 请求如下
curl --location --request POST http://localhost:8082/order?userIduser202103032042012commodityCode100202003032041count20money200如图 测试发现当库存不足时如果余额已经扣减并不会回滚出现了分布式事务问题。
2.理论基础
解决分布式事务问题需要一些分布式系统的基础知识作为理论指导。
2.1.CAP定理
1998年加州大学的计算机科学家 Eric Brewer 提出分布式系统有三个指标。 Consistency一致性Availability可用性Partition tolerance 分区容错性 它们的第一个字母分别是 C、A、P。 Eric Brewer 说这三个指标不可能同时做到。这个结论就叫做 CAP 定理。
2.1.1.一致性
Consistency一致性用户访问分布式系统中的任意节点得到的数据必须一致。
比如现在包含两个节点其中的初始数据是一致的 当我们修改其中一个节点的数据时两者的数据产生了差异 要想保住一致性就必须实现node01 到 node02的数据 同步
2.1.2.可用性
Availability 可用性用户访问集群中的任意健康节点必须能得到响应而不是超时或拒绝。
如图有三个节点的集群访问任何一个都可以及时得到响应 当有部分节点因为网络故障或其它原因无法访问时代表节点不可用
2.1.3.分区容错
Partition分区因为网络故障或其它原因导致分布式系统中的部分节点与其它节点失去连接形成独立分区。 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) 这里的子系统事务称为分支事务有关联的各个分支事务在一起称为全局事务。 3.初识Seata Seata是 2019 年 1 月份蚂蚁金服和阿里巴巴共同开源的分布式事务解决方案。致力于提供高性能和简单易用的分布式事务服务为用户打造一站式的分布式解决方案。
官网地址http://seata.io/其中的文档、播客中提供了大量的使用说明、源码分析。
3.1.Seata的架构 【理解】
Seata事务管理中有三个重要的角色 TC (Transaction Coordinator) - 事务协调者 维护全局和分支事务的状态协调全局事务提交或回滚。 TM (Transaction Manager) - 事务管理器 定义全局事务的范围、开始全局事务、提交或回滚全局事务。 RM (Resource Manager) - 资源管理器 管理分支事务处理的资源与TC交谈以注册分支事务和报告分支事务的状态并驱动分支事务提交或回滚 。
整体的架构如图 Seata基于上述架构提供了四种不同的分布式事务解决方案
XA模式强一致性分阶段事务模式牺牲了一定的可用性无业务侵入TCC模式最终一致的分阶段事务模式有业务侵入AT模式最终一致的分阶段事务模式无业务侵入也是Seata的默认模式SAGA模式长事务模式有业务侵入
无论哪种方案都离不开TC也就是事务的协调者。
3.2.部署TC服务 【重要不需要背过参照文档就可以】
参考课前资料提供的文档《 seata的部署和集成.md 》 https://editor.csdn.net/md?articleId128410730
3.3.微服务集成Seata 【重要】
我们以order-service为例来演示。 实际中每个微服务都要集成一遍Seata参与全局事务的每个微服务都要做这个动作
3.3.1.引入依赖
首先在order-service中引入依赖
!--seata--
dependencygroupIdcom.alibaba.cloud/groupIdartifactIdspring-cloud-starter-alibaba-seata/artifactIdexclusions !--代表排除也要写--!--版本较低1.3.0因此排除-- exclusionartifactIdseata-spring-boot-starter/artifactIdgroupIdio.seata/groupId/exclusion/exclusions
/dependency
dependencygroupIdio.seata/groupIdartifactIdseata-spring-boot-starter/artifactId!--seata starter 采用1.4.2版本--version${seata.version}/version !--在父工程中有定义版本也可以直接写版本号--
/dependency3.3.2.配置TC地址 在order-service中的application.yml中配置TC服务信息通过注册中心nacos结合服务名称获取TC地址 下面的是要根据自己的实际来更改的 group: DEFAULT_GROUP # 分组默认是DEFAULT_GROUP 与nacos浏览器显示的是一样的application: seata-tc-server # seata服务名称 与部署TC服务时是一样的seata-demo: SH #将seata-demo映射到SH集群seata:registry: # TC服务注册中心的配置微服务根据这些信息去注册中心获取tc服务地址# 参考tc服务自己的registry.conf中的配置# 包括地址、namespace、group、application-name 、clustertype: nacos # 注册中心类型 nacosnacos: # tcserver-addr: 127.0.0.1:8848 # nacos地址namespace: # namespace默认为空空就是publicgroup: DEFAULT_GROUP # 分组默认是DEFAULT_GROUP 与nacos浏览器显示的是一样的application: seata-tc-server # seata服务名称 与部署TC服务时是一样的username: nacospassword: nacostx-service-group: seata-demo # 事务组名称根据这个获取tc服务的cluster集群名称service:vgroup-mapping: # 事务组与cluster的映射关系seata-demo: SH #将seata-demo映射到SH集群微服务如何根据这些配置寻找TC的地址呢
我们知道注册到Nacos中的微服务确定一个具体实例需要四个信息
namespace命名空间group分组application服务名cluster集群名
以上四个信息在刚才的yaml文件中都能找到 namespace为空就是默认的public
结合起来TC服务的信息就是publicDEFAULT_GROUPseata-tc-serverSH这样就能确定TC服务集群了。然后就可以去Nacos拉取对应的实例信息了。
3.3.3.其它服务 其它两个微服务也都参考order-service的步骤来做完全一样。
3.3.4.小结 4.动手实践
下面我们就一起学习下Seata中的四种不同的事务模式。
4.1.XA模式 【重要用的少】 XA 规范 是 X/Open 组织定义的分布式事务处理DTPDistributed Transaction Processing标准XA 规范 描述了全局的TM与局部的RM之间的接口几乎所有主流的数据库都对 XA 规范 提供了支持。
4.1.1.两阶段提交 XA是规范目前主流数据库都实现了这种规范实现的原理都是基于两阶段提交。
正常情况 异常情况 一阶段
事务协调者通知每个事物参与者执行本地事务本地事务执行完成后报告事务执行状态给事务协调者此时事务不提交继续持有数据库锁
二阶段
事务协调者基于一阶段的报告来判断下一步操作 如果一阶段都成功则通知所有事务参与者提交事务如果一阶段任意一个参与者失败则通知所有事务参与者回滚事务
4.1.2.Seata的XA模型 【理解即可】 Seata对原始的XA模式做了简单的封装和改造以适应自己的事务模型基本架构如图 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模式
seata:data-source-proxy-mode: XA2给发起全局事务的入口方法添加GlobalTransactional注解: 本例中是OrderServiceImpl中的create方法. 3重启服务并测试 重启order-service等每个微服务再次测试发现无论怎样三个微服务都能成功回滚。
4.2.AT模式 【重要重要】 AT模式同样是分阶段提交的事务模型不过弥补了XA模型中资源锁定周期过长的缺陷。
4.2.1.Seata的AT模型 【理解】
基本流程图 阶段一RM的工作
注册分支事务记录undo-log数据快照执行业务sql并提交报告事务状态
阶段二提交时RM的工作
删除undo-log即可
阶段二回滚时RM的工作
根据undo-log恢复数据到更新前
4.2.2.流程梳理
我们用一个真实的业务来梳理下AT模式的原理。 比如现在又一个数据库表记录用户余额
idmoney1100
其中一个分支业务要执行的SQL为
update tb_account set money money - 10 where id 1AT模式下当前分支事务执行流程如下 一阶段
1TM发起并注册全局事务到TC 2TM调用分支事务 3分支事务准备执行业务SQL 4RM拦截业务SQL根据where条件查询原始数据形成快照。
{id: 1, money: 100
}5RM执行业务SQL提交本地事务释放数据库锁。此时 money 90 6RM报告本地事务状态给TC
二阶段
1TM通知TC事务结束 2TC检查分支事务状态 a如果都成功则立即删除快照 b如果有分支事务失败需要回滚。读取快照数据{id: 1, money: 100}将快照恢复到数据库。此时数据库再次恢复为100
流程图
4.2.3.AT与XA的区别
简述AT模式与XA模式最大的区别是什么
XA模式一阶段不提交事务锁定资源AT模式一阶段直接提交不锁定资源。XA模式依赖数据库机制实现回滚AT模式利用数据快照实现数据回滚。XA模式强一致AT模式最终一致
4.2.4.脏写问题 【理解】
在多线程并发访问AT模式的分布式事务时有可能出现脏写问题如图 解决思路就是引入了全局锁的概念。在释放DB锁数据库锁之前先拿到全局锁。避免同一时刻有另外一个事务来操作当前数据。 实际还可能存在见缝插针的问题 解决办法使用了两个快照更新前的快照、更新后的快照如果出现问题就会申请人工介入
4.2.5.优缺点
AT模式的优点
一阶段完成直接提交事务释放数据库资源性能比较好利用全局锁实现读写隔离没有代码侵入框架自动完成回滚和提交
AT模式的缺点
两阶段之间属于软状态属于最终一致框架的快照功能会影响性能但比XA模式要好很多
4.2.6.实现AT模式 【重要】 AT模式中的快照生成、回滚等动作都是由框架自动完成没有任何代码侵入因此实现非常简单。 只不过AT模式需要一个表来记录全局锁、另一张表来记录数据快照undo_log。 【需要两张表分别记录全局锁和数据快照这两张表分别在不同的数据库中】
1导入数据库表记录全局锁 导入课前资料提供的Sql文件seata-at.sql其中 lock_table全局锁导入到TC服务关联的数据库seata undo_log快照表导入到微服务关联的数据库seata_demo
DROP TABLE IF EXISTS lock_table;
CREATE TABLE lock_table (row_key varchar(128) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL,xid varchar(96) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL,transaction_id bigint(20) NULL DEFAULT NULL,branch_id bigint(20) NOT NULL,resource_id varchar(256) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL,table_name varchar(32) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL,pk varchar(36) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL,gmt_create datetime NULL DEFAULT NULL,gmt_modified datetime NULL DEFAULT NULL,PRIMARY KEY (row_key) USING BTREE,INDEX idx_branch_id(branch_id) USING BTREE
) ENGINE InnoDB CHARACTER SET utf8 COLLATE utf8_general_ci ROW_FORMAT Compact;DROP TABLE IF EXISTS undo_log;
CREATE TABLE undo_log (branch_id bigint(20) NOT NULL COMMENT branch transaction id,xid varchar(100) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL COMMENT global transaction id,context varchar(128) CHARACTER SET utf8 COLLATE utf8_general_ci 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(6) NOT NULL COMMENT create datetime,log_modified datetime(6) NOT NULL COMMENT modify datetime,UNIQUE INDEX ux_undo_log(xid, branch_id) USING BTREE
) ENGINE InnoDB CHARACTER SET utf8 COLLATE utf8_general_ci COMMENT AT transaction mode undo table ROW_FORMAT Compact;2修改application.yml文件每个参与事务的微服务将事务模式修改为AT模式即可
seata:data-source-proxy-mode: AT # 默认就是AT3重启所有有关的微服务并测试 重启order-service等每个微服务再次测试发现无论怎样三个微服务都能成功回滚。
4.3.TCC模式 【重要重要】 注意 并不是所有的微服务都适合使用TCC模式可以一部分使用AT一部分使用TCCAT和TCC可以混用
TCC模式与AT模式非常相似每阶段都是独立事务不同的是TCC通过人工编码来实现数据恢复。需要实现三个方法
Try资源的检测和预留Confirm完成资源操作业务要求 Try 成功 Confirm 一定要能成功。Cancel预留资源释放可以理解为try的反向操作。
4.3.1.流程分析 【理解】
举例一个扣减用户余额的业务。假设账户A原来余额是100需要余额扣减30元。 阶段一 Try 检查余额是否充足如果充足则冻结金额增加30元可用余额扣除30 初识余额 余额充足可以冻结 此时总金额 冻结金额 可用金额数量依然是100不变。事务直接提交无需等待其它事务。 阶段二Confirm)假如要提交Confirm则冻结金额扣减30 确认可以提交不过之前可用金额已经扣减过了这里只要清除冻结金额就好啦 此时总金额 冻结金额 可用金额 0 70 70元 阶段二(Canncel)如果要回滚Cancel则冻结金额扣减30可用余额增加30 需要回滚那么就要释放冻结金额恢复可用金额
4.3.2.Seata的TCC模型 【理解】
Seata 中的 TCC模型 依然延续之前的事务架构如图
4.3.3.优缺点
TCC模式的每个阶段是做什么的
Try资源检查和预留Confirm业务执行和提交Cancel预留资源的释放
TCC的优点是什么
一阶段完成直接提交事务释放数据库资源性能好相比AT模型无需生成快照无需使用全局锁性能最强不依赖数据库事务而是依赖补偿操作可以用于非事务型数据库
TCC的缺点是什么【消耗人】
有代码侵入需要人为编写try、Confirm和Cancel接口太麻烦软状态事务是最终一致需要考虑Confirm和Cancel的失败情况做好幂等处理
4.3.4.事务悬挂和空回滚 【重要】
1空回滚 当某分支事务的try阶段阻塞时可能导致全局事务超时而触发二阶段的cancel操作。在未执行try操作时先执行了cancel操作这时cancel不能做回滚就是空回滚。 如图 执行cancel操作时应当判断try是否已经执行如果尚未执行则应该空回滚。
2业务悬挂 对于已经空回滚的业务之前被阻塞的try操作恢复但是它恢复的太迟了整个全局事务已经结束了继续执行try就永远不可能confirm或cancel 事务一直处于中间状态这就是业务悬挂。 执行try操作时应当判断cancel是否已经执行过了如果已经执行应当阻止空回滚后的try操作避免悬挂
4.3.5.实现TCC模式 【重要】 注意 并不是所有的微服务都适合使用TCC模式可以一部分使用AT一部分使用TCCAT和TCC可以混用 解决空回滚和业务悬挂问题必须要记录当前事务状态是在try、还是cancel
1思路分析
为了实现空回滚、防止业务悬挂以及幂等性要求。我们必须在数据库记录冻结金额的同时记录当前事务id和执行状态为此我们设计了一张表 在微服务的数据库seata_demo中执行创建
CREATE TABLE account_freeze_tbl (xid varchar(128) NOT NULL,user_id varchar(255) DEFAULT NULL COMMENT 用户id,freeze_money int(11) unsigned DEFAULT 0 COMMENT 冻结金额,state int(1) DEFAULT NULL COMMENT 事务状态0:try1:confirm2:cancel,PRIMARY KEY (xid) USING BTREE
) ENGINEInnoDB DEFAULT CHARSETutf8 ROW_FORMATCOMPACT;其中
xid是全局事务idfreeze_money用来记录用户冻结金额state用来记录事务状态
那此时我们的业务该怎么做呢
Try业务 记录冻结金额和事务状态到account_freeze表扣减account表可用金额 Confirm业务 根据xid删除account_freeze表的冻结记录 Cancel业务 修改account_freeze表冻结金额为0state为2修改account表恢复可用金额 如何判断是否空回滚 cancel业务中根据xid查询account_freeze_tbl表如果为null则说明try还没做需要空回滚 如何避免业务悬挂 try业务中根据xid查询account_freeze_tbl表 如果已经存在则证明Cancel已经执行拒绝执行try业务
接下来我们改造account-service利用TCC实现余额扣减功能。
2声明TCC接口
TCC的Try、Confirm、Cancel方法都需要在接口中基于注解来声明
我们在account-service账户微服务项目中的cn.itcast.account.service包中新建一个接口声明TCC三个接口
package cn.itcast.account.service;LocalTCC
public interface AccountTCCService {TwoPhaseBusinessAction(name deduct, commitMethod confirm, rollbackMethod cancel)//给参数加注解在deduct方法中BusinessActionContextParametervoid deduct(BusinessActionContextParameter(paramName userId) String userId,BusinessActionContextParameter(paramName money)int money);boolean confirm(BusinessActionContext ctx); //BusinessActionContext ct上下文对象可以获取当前的事务信息和参数信息前提是要给参数加注解在deduct方法中BusinessActionContextParameterboolean cancel(BusinessActionContext ctx);//BusinessActionContext ct上下文对象可以获取当前的事务信息和参数信息
}2编写实体类
账户实体类 记录当前事务id和执行状态的实体类对应上面创建的account_freeze_tbl数据表 2编写mapper操作数据表
操作记录当前事务id和执行状态数据表对应上面创建的account_freeze_tbl数据表
操作账户数据表
3编写实现类 不全需要看代码补全
在account-service服务中的cn.itcast.account.service.impl包下新建一个类实现TCC业务
package cn.itcast.account.service.impl;Service
Slf4j
public class AccountTCCServiceImpl implements AccountTCCService {Autowiredprivate AccountMapper accountMapper;//下面Try方法要操作两张表把两张表的mapper层的方法注入进来Autowiredprivate AccountFreezeMapper freezeMapper; //下面Try方法要操作两张表把两张表的mapper层的方法注入进来OverrideTransactional //下面一抛异常走到这里回滚public void deduct(String userId, int money) { //Try方法// 0.获取事务idString xid RootContext.getXID(); //拿到全局事务id// 1.扣减可用余额accountMapper.deduct(userId, money); //调用mapper层的操作数据库方法// 2.记录冻结金额事务状态AccountFreeze freeze new AccountFreeze(); //AccountFreeze的实体类freeze.setUserId(userId);freeze.setFreezeMoney(money);freeze.setState(AccountFreeze.State.TRY);freeze.setXid(xid); //使用 // 0.获取事务idfreezeMapper.insert(freeze); //调用mapper层的操作数据库方法}Overridepublic boolean confirm(BusinessActionContext ctx) {// 1.获取事务idString xid ctx.getXid();// 2.根据id删除冻结记录int count freezeMapper.deleteById(xid); //调用mapper层的操作数据库方法return count 1;}Overridepublic boolean cancel(BusinessActionContext ctx) {// 0.查询冻结记录String xid ctx.getXid();AccountFreeze freeze freezeMapper.selectById(xid); //得到freeze对象// 1.恢复可用余额//参数是用户id和金额accountMapper.refund(freeze.getUserId(), freeze.getFreezeMoney());// 2.将冻结金额清零状态改为CANCELfreeze.setFreezeMoney(0); //冻结金额清零freeze.setState(AccountFreeze.State.CANCEL); //修改状态为CANCELint count freezeMapper.updateById(freeze); //调用mapper层的操作数据库方法return count 1;}
}4.4.SAGA模式 【没怎么说】
Saga 模式是 Seata 即将开源的长事务解决方案将由蚂蚁金服主要贡献。
其理论基础是Hector Kenneth 在1987年发表的论文Sagas。
Seata官网对于Saga的指南https://seata.io/zh-cn/docs/user/saga.html
4.4.1.原理
在 Saga 模式下分布式事务内有多个参与者每一个参与者都是一个冲正补偿服务需要用户根据业务场景实现其正向操作和逆向回滚操作。
分布式事务执行过程中依次执行各参与者的正向操作如果所有正向操作均执行成功那么分布式事务提交。如果任何一个正向操作执行失败那么分布式事务会去退回去执行前面各参与者的逆向回滚操作回滚已提交的参与者使分布式事务回到初始状态。 Saga也分为两个阶段
一阶段直接提交本地事务二阶段成功则什么都不做失败则通过编写补偿业务来回滚
4.4.2.优缺点
优点
事务参与者可以基于事件驱动实现异步调用吞吐高一阶段直接提交事务无锁性能好不用编写TCC中的三个阶段实现简单
缺点
软状态持续时间不确定时效性差没有锁没有事务隔离会有脏写
4.5.四种模式对比
我们从以下几个方面来对比四种实现
一致性能否保证事务的一致性强一致还是最终一致隔离性事务之间的隔离性如何代码侵入是否需要对业务代码改造性能有无性能损耗场景常见的业务场景
如图
5.高可用 【重要】
Seata的TC服务作为分布式事务核心一定要保证集群的高可用性。
5.1.高可用架构模型
搭建TC服务集群非常简单启动多个TC服务注册到nacos即可。 但集群并不能确保100%安全万一集群所在机房故障怎么办所以如果要求较高一般都会做异地多机房容灾。
比如一个TC集群在上海另一个TC集群在杭州 微服务基于事务组tx-service-group)与TC集群的映射关系来查找当前应该使用哪个TC集群。当SH集群故障时只需要将vgroup-mapping中的映射关系改成HZ。则所有微服务就会切换到HZ的TC集群了。
5.2.实现高可用
具体实现请参考课前资料提供的文档《seata的部署和集成.md》
第三章节 直接参考https://editor.csdn.net/md?articleId128410730即可 【# 叁、TC服务的高可用和异地容灾】