前言
本章节介绍分布式事务框架seata TCC模式,上一章节介绍seata以及集成到Springboot、微服务框架里。
1、TCC模式
一个分布式的全局事务,整体是 两阶段提交 的模型。全局事务是由若干分支事务组成的,分支事务要满足 两阶段提交 的模型要求,即需要每个分支事务都具备自己的:
- 一阶段 prepare 行为
- 二阶段 commit 或 rollback 行为
根据两阶段行为模式的不同,我们将分支事务划分为 Automatic (Branch) Transaction Mode 和 TCC (Branch) Transaction Mode.
1.1、AT 模式(参考链接 TBD)基于 支持本地 ACID 事务 的 关系型数据库
1.1.1、 一阶段 prepare 行为
在本地事务中,一并提交业务数据更新和相应回滚日志记录。
1.1.2、二阶段 commit 行为
马上成功结束,自动 异步批量清理回滚日志。
1.1.3、二阶段 rollback 行为
通过回滚日志,自动 生成补偿操作,完成数据回滚。
1.2、TCC 模式,不依赖于底层数据资源的事务支持
1.2.1、一阶段 prepare 行为
调用 自定义 的 prepare 逻辑。try
1.2.2、二阶段 commit 行为
调用 自定义 的 commit 逻辑。confirm
1.2.3、二阶段 rollback 行为
调用 自定义 的 rollback 逻辑。cancel
2、例子
2.1、定义controller
/** * 采购 */ @PostMapping("/purchaseTCC") @GlobalTransactional public String purchaseTCC(@RequestBody OrderDTO orderDTO){ this.businessTCCService.purchase(orderDTO); return "success"; }
2.2、定义service
@LocalTCC public interface BusinessTCCService { /** * 采购 执行资源检查及预留操作 */ @TwoPhaseBusinessAction(name = "purchase",commitMethod = "commit",rollbackMethod = "rollback") public void purchase(@BusinessActionContextParameter(paramName = "orderDTO") OrderDTO orderDTO); /** * 全局事务进行提交 * @param businessActionContext * @return */ boolean commit(BusinessActionContext businessActionContext); /** * 全局事务进行不回滚 * @param businessActionContext * @return */ boolean rollback(BusinessActionContext businessActionContext); }
package com.xxxx.store.business.service.impl; import cn.hutool.crypto.SecureUtil; import com.alibaba.fastjson.JSON; import com.alibaba.fastjson.JSONObject; import com.xxxx.store.business.service.BusinessService; import com.xxxx.store.business.service.BusinessTCCService; import com.xxxx.store.business.service.OrderService; import com.xxxx.store.business.service.StorageService; import com.xxxx.store.common.dto.OrderDTO; import com.xxxx.store.common.dto.StorageDTO; import io.seata.rm.tcc.api.BusinessActionContext; import io.seata.spring.annotation.GlobalTransactional; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Value; import org.springframework.stereotype.Service; import java.io.File; @Service public class BusinessTCCServiceImpl implements BusinessTCCService { @Value("${file.path}") private String filePath; @Autowired private OrderService orderService; @Autowired private StorageService storageService; @Override public void purchase(OrderDTO orderDTO) { //减库存 this.storageService.deduct(new StorageDTO(null,orderDTO.getCommodityCode(),orderDTO.getCount())); //创建订单 this.orderService.create(orderDTO); } @Override public boolean commit(BusinessActionContext businessActionContext) { System.out.println("事务ID:" + businessActionContext.getXid()); return true; } @Override public boolean rollback(BusinessActionContext businessActionContext) { JSONObject jSONObject = (JSONObject)businessActionContext.getActionContext("orderDTO"); OrderDTO orderDTO = jSONObject.toJavaObject(OrderDTO.class); StorageDTO storageDTO = new StorageDTO(null, orderDTO.getCommodityCode(), orderDTO.getCount()); String s = JSON.toJSONString(storageDTO); String md5 = SecureUtil.md5(s); System.out.println("**************触发回滚操作:" + filePath + md5); File file = new File(filePath + md5); file.delete(); return true; } /*@Override public void purchase(OrderDTO orderDTO) { //减库存 this.storageService.deduct(new StorageDTO(null,orderDTO.getCommodityCode(),orderDTO.getCount())); //创建订单 this.orderService.create(orderDTO); }*/ }
注解 | 描述 |
@LocalTCC | 一定需要注解在接口上,否则不生效,此接口可以是寻常的业务接口,只要实现了TCC的两阶段提交对应方法便可,适用于SpringCloud+Feign模式下的TCC。 |
@TwoPhaseBusinessAction | 注解try方法,其中name为当前tcc方法的bean名称,写方法名便可(全局唯一),commitMethod指向提交方法,rollbackMethod指向事务回滚方法。指定好三个方法之后,seata会根据全局事务的成功或失败,自动调用提交方法或者回滚方法。 |
@BusinessActionContextParameter | 使用该注解可以将参数传递到二阶段commit或者rollback的方法中,方便调用。 |
BusinessActionContext | TCC事务上下文,使用BusinessActionContext.getActionContext(“params”)便可以得到一阶段try中定义的参数,在二阶段参考此参数进行业务回滚操作。 |
建议:可以在try方法中使用@Transational,直接通过spring来控制关系型数据库的事务,进行回滚的操作,而非关系型数据库等中间件的回滚操作可以交给rollbackMethod方法处理。
建议:try接口不可以捕获异常,否则TCC将识别该操作为成功,直接执行二阶段commit方法。