如何通过域名访问网站,长沙学网页设计的学校有哪些,wordpress中文是什么意思,软件开发流程书籍一 TCC模式
1.1 TCC的逻辑
TCC模式与AT模式非常相似#xff0c;每阶段都是独立事务#xff0c;不同的是TCC需要人工干预编写代码。需要实现三个方法#xff1a; Try#xff1a;资源的检测和预留#xff1b; Confirm#xff1a;完成资源操作业务#xff1b;要求 Try 成…一 TCC模式
1.1 TCC的逻辑
TCC模式与AT模式非常相似每阶段都是独立事务不同的是TCC需要人工干预编写代码。需要实现三个方法 Try资源的检测和预留 Confirm完成资源操作业务要求 Try 成功 Confirm 一定要能成功。 Cancel预留资源释放可以理解为try的反向操作。
1.2 流程图 TCC的执行流程可以分为两个阶段分别如下
1第一阶段Try业务系统做检测并预留资源 (加锁锁住资源)比如常见的下单在try阶段我们不是真正的减库存而是把下单的库存给锁定住。
2第二阶段根据第一阶段的结果决定是执行confirm还是cancel
Confirm执行真正的业务执行业务释放锁 Cancle是对Try阶段预留资源的释放出问题释放锁 原文链接https://blog.csdn.net/a745233700/article/details/122402303 1.3 优缺点 一阶段完成直接提交事务释放数据库资源性能好 相比AT模型无需生成快照无需使用全局锁性能最强 不依赖数据库事务而是依赖补偿操作可以用于非事务型数据库
TCC的缺点是什么 有代码侵入需要人为编写try、Confirm和Cancel接口太麻烦 软状态事务是最终一致 需要考虑Confirm和Cancel的失败情况做好幂等处理
1.4 实现空回滚与悬挂
当某分支事务的try阶段阻塞时可能导致全局事务超时而触发二阶段的cancel操作。在未执行try操作时先执行了cancel操作这时cancel不能做回滚就是空回滚。 2.空悬挂
对于已经空回滚的业务之前被阻塞的try操作恢复继续执行try就永远不可能confirm或cancel 事务一直处于中间状态这就是业务悬挂。
执行try操作时应当判断cancel是否已经执行过了如果已经执行应当阻止空回滚后的try操作避免悬挂
二 利用TCC实现分布式事务的案例操作
2.1 工程结构 2.2 需求的描述
1.修改account-service编写tryconfirmcancel逻辑
2.try业务 添加冻结金额扣减可用金额
3.confirm业务删除冻结金额
4.cancel业务删除冻结金额恢复可用金额 2.3 解决空回滚和悬挂
为了防止空回滚业务悬挂保证幂等性要求需要新增一张表冻结表在数据库记录冻结金额的同时记录当前事务id和执行状态。如下图所示 2.4 附件数据库 2.5 编写tryconfirmcancel方法
1.在account-service模块新增接口
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 deductInfo, commitMethod confirm, rollbackMethod cancel)void deduct(BusinessActionContextParameter(paramName userId) String userId,BusinessActionContextParameter(paramName money)int money);boolean confirm(BusinessActionContext ctx);boolean cancel(BusinessActionContext ctx);
}2.定义实现类
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();// 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();AccountFreeze freeze freezeMapper.selectById(xid);// 1.恢复可用余额accountMapper.refund(freeze.getUserId(), freeze.getFreezeMoney());// 2.将冻结金额清零状态改为CANCELfreeze.setFreezeMoney(0);freeze.setState(AccountFreeze.State.CANCEL);int count freezeMapper.updateById(freeze);return count 1;}
}3.修改controller调用 2.6 启动nacosseata
1.启动nacos 2.启动seata 2.7 验证
2.7.1 初始态数据表 2.7.2 正常下单
1.请求 http://localhost:8082/order?userIduser202103032042012commodityCode100202003032041count1money50 2.各表数据 2.7.3 订单数大于库存数访问
1.请求http://localhost:8082/order?userIduser202103032042012commodityCode100202003032041count10money50 2.查看控制台
account 2.order 3.storage 3.查看数据表回滚执行了cancel方法冻结表新增一条冻结数据其他表均进行了回滚。