网站 利润,网站模版化配置,网站中超链接怎么做,网站如何做品牌宣传文章目录 解决分布式事务的思路seata四种模式1. XA模式2. AT模式AT模式与XA模式的区别是什么#xff1f;脏写问题 3. TCC模式事务悬挂和空回滚 4. SAGA模式 四种模式对比口述AT模式与TCC模式高可用 什么是分布式事务#xff1f; 分布式事务#xff0c;就是指不是在单个服务或… 文章目录 解决分布式事务的思路seata四种模式1. XA模式2. AT模式AT模式与XA模式的区别是什么脏写问题 3. TCC模式事务悬挂和空回滚 4. SAGA模式 四种模式对比口述AT模式与TCC模式高可用 什么是分布式事务 分布式事务就是指不是在单个服务或单个数据库架构下产生的事务例如
跨数据源的分布式事务跨服务的分布式事务综合情况
例如电商行业中比较常见的下单付款案例包括下面几个行为
创建新订单扣减商品库存从用户账户余额扣除金额 订单的创建、库存的扣减、账户扣款在每一个服务和数据库内是一个本地事务可以保证ACID原则。
但是当我们把三件事情看做一个业务要满足保证“业务”的原子性要么所有操作全部成功要么全部失败不允许出现部分成功部分失败的现象这就是分布式系统下的事务了。
此时ACID难以满足这是分布式事务要解决的问题 CAP理论 Consistency一致性用户访问分布式系统中的任意节点得到的数据必须一致。 Availability 可用性用户访问集群中的任意健康节点必须能得到响应而不是超时或拒绝。 Partition分区**因为网络故障或其它原因导致分布式系统中的部分节点与其它节点失去连接形成独立分区。
解决分布式事务的思路
分布式事务最大的问题是各个子事务的一致性问题因此可以借鉴CAP定理和BASE理论有两种解决思路
AP模式各子事务分别执行和提交允许出现结果不一致然后采用弥补措施恢复数据即可实现最终一致。CP模式各个子事务执行后互相等待同时提交同时回滚达成强一致。但事务等待过程中处于弱可用状态。
seata事务管理
Seata事务管理中有三个重要的角色
TC (Transaction Coordinator) - 事务协调者维护全局和分支事务的状态协调全局事务提交或回滚。TM (Transaction Manager) - 事务管理器定义全局事务的范围、开始全局事务、提交或回滚全局事务。RM (Resource Manager) - 资源管理器管理分支事务处理的资源与TC交谈以注册分支事务和报告分支事务的状态并驱动分支事务提交或回滚。 微服务集成seata
引入依赖 配置TC地址
seata四种模式
Seata提供了四种不同的分布式事务解决方案
XA模式强一致性分阶段事务模式牺牲了一定的可用性无业务侵入AT模式最终一致的分阶段事务模式无业务侵入也是Seata的默认模式TCC模式最终一致的分阶段事务模式有业务侵入SAGA模式长事务模式有业务侵入
1. XA模式
Seata对原始的XA模式做了简单的封装和改造以适应自己的事务模型基本架构如图
XA模式的优点是什么
事务的强一致性满足ACID原则。常用数据库都支持实现简单并且没有代码侵入
XA模式的缺点是什么
因为一阶段需要锁定数据库资源等待二阶段结束才释放性能较差依赖关系型数据库实现事务
实现XA模式
2. AT模式
AT模式同样是分阶段提交的事务模型不过缺弥补了XA模型中资源锁定周期过长的缺陷。
AT模式下执行流程
一阶段
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
AT模式与XA模式的区别是什么
XA模式一阶段不提交事务锁定资源AT模式一阶段直接提交不锁定资源。XA模式依赖数据库机制实现回滚AT模式利用数据快照实现数据回滚。XA模式强一致AT模式最终一致
脏写问题
口述因为AT模式是两阶段的事务模型在第一个阶段分支事务执行之前首先会记录数据快照然后执行对应sql然后就释放了数据库锁那么在他释放后这一时刻另一个事务就能拿到数据库锁然后对同一个数据又进行了修改那么第一个事务在第二阶段回滚恢复快照时就会覆盖另一个事务的修改。
在多线程并发访问AT模式的分布式事务时有可能出现脏写问题如图
解决思路就是引入了全局锁的概念。在释放DB锁之前先拿到全局锁。避免同一时刻有另外一个事务来操作当前数据。 AT模式的优点
一阶段完成直接提交事务释放数据库资源性能比较好利用全局锁实现读写隔离没有代码侵入框架自动完成回滚和提交
AT模式的缺点
两阶段之间属于软状态属于最终一致框架的快照功能会影响性能但比XA模式要好很多
3. TCC模式
TCC模式与AT模式非常相似每阶段都是独立事务不同的是TCC通过人工编码来实现数据恢复。需要实现三个方法
Try资源的检测和预留Confirm完成资源操作业务要求 Try 成功 Confirm 一定要能成功。Cancel预留资源释放可以理解为try的反向操作。 TCC的优点是什么
一阶段完成直接提交事务释放数据库资源性能好相比AT模型无需生成快照无需使用全局锁性能最强不依赖数据库事务而是依赖补偿操作可以用于非事务型数据库
TCC的缺点是什么
有代码侵入需要人为编写try、Confirm和Cancel接口太麻烦软状态事务是最终一致需要考虑Confirm和Cancel的失败情况做好幂等处理
事务悬挂和空回滚
空回滚 当某分支事务的try阶段阻塞时可能导致全局事务超时而触发二阶段的cancel操作。在未执行try操作时先执行了cancel操作这时cancel不能做回滚就是空回滚。 业务悬挂 对于已经空回滚的业务之前被阻塞的try操作恢复继续执行try就永远不可能confirm或cancel 事务一直处于中间状态这就是业务悬挂。
执行try操作时应当判断cancel是否已经执行过了如果已经执行应当阻止空回滚后的try操作避免悬挂 实现TCC模式案例 解决空回滚和业务悬挂问题必须要记录当前事务状态是在try、还是cancel
这里我们定义一张冻结表 其中
xid是全局事务idfreeze_money用来记录用户冻结金额state用来记录事务状
那此时我们的业务开怎么做呢
Try业务 记录冻结金额和事务状态state0到account_freeze表扣减account表可用金额 Confirm业务 根据xid删除account_freeze表的冻结记录 Cancel业务 修改account_freeze表冻结金额为0state为2修改account表恢复可用金额 如何判断是否空回滚 cancel业务中根据xid查询account_freeze如果为null则说明try还没做需要空回滚 如何避免业务悬挂 try业务中根据xid查询account_freeze 如果已经存在则证明Cancel已经执行拒绝执行try业务
声明TCC接口 TCC的Try、Confirm、Cancel方法都需要在接口中基于注解来声明 我们在account-service项目中的cn.itcast.account.service包中新建一个接口声明TCC三个接口
package cn.itcast.account.service;import io.seata.rm.tcc.api.BusinessActionContext;
import io.seata.rm.tcc.api.BusinessActionContextParameter;
import io.seata.rm.tcc.api.LocalTCC;
import io.seata.rm.tcc.api.TwoPhaseBusinessAction;LocalTCC
public interface AccountTCCService {TwoPhaseBusinessAction(name deduct, commitMethod confirm, rollbackMethod cancel)void deduct(BusinessActionContextParameter(paramName userId) String userId,BusinessActionContextParameter(paramName money)int money);boolean confirm(BusinessActionContext ctx);boolean cancel(BusinessActionContext ctx);
}编写实体类 在account-service服务中的cn.itcast.account.service.impl包下新建一个类实现TCC业务
package cn.itcast.account.service.impl;import cn.itcast.account.entity.AccountFreeze;
import cn.itcast.account.mapper.AccountFreezeMapper;
import cn.itcast.account.mapper.AccountMapper;
import cn.itcast.account.service.AccountTCCService;
import io.seata.core.context.RootContext;
import io.seata.rm.tcc.api.BusinessActionContext;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;Service
Slf4j
public class AccountTCCServiceImpl implements AccountTCCService {Autowiredprivate AccountMapper accountMapper;Autowiredprivate AccountFreezeMapper freezeMapper;OverrideTransactionalpublic void deduct(String userId, int money) {// 0.获取事务idString xid RootContext.getXID();// 避免特务悬挂判断freeze表中是否有冻结记录如果有一定是CANDEL执行过了拒绝执行tryAccountFreezeMapper oldFreeze freezeMapper.selectById(xid);if (oldFreeze ! null){return;}// 1.扣减可用余额accountMapper.deduct(userId, money);// 2.记录冻结金额事务状态AccountFreeze freeze new AccountFreeze();freeze.setUserId(userId);freeze.setFreezeMoney(money);freeze.setState(AccountFreeze.State.TRY);freeze.setXid(xid);freezeMapper.insert(freeze);}Overridepublic boolean confirm(BusinessActionContext ctx) {// 1.获取事务idString xid ctx.getXid();// 2.根据id删除冻结记录int count freezeMapper.deleteById(xid);return count 1;}Overridepublic boolean cancel(BusinessActionContext ctx) {// 0.查询冻结记录String xid ctx.getXid();String userId ctx.getActionContext(userId).toString();AccountFreeze freeze freezeMapper.selectById(xid);//空回滚的判断判断freeze是否为null为null证明还没有try需要空回滚if (freeze null){//为null证明还没有try需要空回滚freeze new AccountFreeze();freeze.setUserId(userId);freeze.setFreezeMoney(0);freeze.setState(AccountFreeze.State.CANCEL);freeze.setXid(xid);freezeMapper.insert(freeze);}//判断幂等性if (freeze.getState() AccountFreeze.State.CANCEL){// 已经处理过一次CANCEL了无需重复处理return true;}// 1.恢复可用余额accountMapper.refund(freeze.getUserId(), freeze.getFreezeMoney());// 2.将冻结金额清零状态改为CANCELfreeze.setFreezeMoney(0);freeze.setState(AccountFreeze.State.CANCEL);int count freezeMapper.updateById(freeze);return count 1;}
}4. SAGA模式
分布式事务执行过程中依次执行各参与者的正向操作如果所有正向操作均执行成功那么分布式事务提交。如果任何一个正向操作执行失败那么分布式事务会去退回去执行前面各参与者的逆向回滚操作回滚已提交的参与者使分布式事务回到初始状态。
四种模式对比 口述AT模式与TCC模式
AT模式与TCC模式都是二阶段的分布式事务模型每个分支事务在第一阶段它们执行完后都可以立即提交或回滚当当然有的分支事务能成功有的就回滚了当TC事务调度者来对这些分支事务做统计看看最终是将这些事务提交还是回滚AT模式下的话它是基于数据快照形式的在操作数据库之前会保存数据库修改前的数据快照当需要回滚时恢复这些快照就可以AT下的话还使用了全局锁来避免第一阶段与第二阶段这个时间内的脏写问题; TCC模式的话其实核心就是三个接口Try、confirm、cancel它在第一阶段是会进行try操作就是资源的预留的就是吧对应想操作的数据记录到一张表中 第二个阶段如果要是提交的话就是执行confirm里面的代码它直接删除我们表中的数据就可以如果要回滚的话其实就是执行cancel这个方法的代码其实类似于执行try的反向操作。这里面的话需要注意空回滚与业务悬挂就是在try与cancel中来进行具体的判断。
高可用
搭建TC服务集群非常简单启动多个TC服务注册到nacos即可。 但集群并不能确保100%安全万一集群所在机房故障怎么办所以如果要求较高一般都会做异地多机房容灾。 在nacos配置中心配置配置热更新