Seata分布式事物(三)TCC事务模式执行机制

Seata的AT模式基本上能满足我们使用分布式事务80%的需求,但涉及不支持事务的数据库与中间件(如redis)等的操作,或AT模式暂未支持的数据库(目前AT支持Mysql、Oracle与PostgreSQL)、跨公司服务的调用、跨语言的应用调用或有手动控制整个二阶段提交过程的需求,则需要结合TCC模式。不仅如此,TCC模式还支持与AT模式混合使用。

1、TCC模式的概念

一个分布式的全局事务,整体是两阶段提交Try-[Comfirm/Cancel] 的模型。在Seata中,AT模式与TCC模式事实上都是两阶段提交的具体实现。他们的区别在于:

  • AT 模式基于支持本地 ACID (原子性、一致性、隔离性和持久性)事务 的 关系型数据库(目前支持Mysql、Oracle与PostgreSQL):

    • 一阶段 prepare 行为:在本地事务中,一并提交业务数据更新和相应回滚日志记录。
    • 二阶段 commit 行为:马上成功结束,自动异步批量清理回滚日志。
    • 二阶段 rollback 行为:通过回滚日志,自动生成补偿操作,完成数据回滚。
  • TCC 模式,不依赖于底层数据资源的事务支持,需要人为编写代码实现提交和回滚操作

    • 一阶段 prepare 行为:调用 自定义 的 prepare 逻辑(实际业务逻辑)。
    • 二阶段 commit 行为:调用 自定义的 commit 逻辑。
    • 二阶段 rollback 行为:调用 自定义的 rollback 逻辑。

所谓 TCC 模式,是指支持把 自定义 的分支事务的提交和回滚纳入到全局事务的管理中。

通俗讲,SEATA的TCC模式就是手工的AT模式,它允许你自定义两阶段的处理逻辑而不依赖AT模式的undo_log。
在这里插入图片描述

2、业务代码处理

对业务接口进行定义处理。

  1. seata.jar、配置文件正常配置即可,可以参考Seata分布式事物(一)

  2. 在业务接口实例

    
    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;
    
    import java.math.BigDecimal;
    
    @LocalTCC
    public interface AccountService {
    
        /**
         * 扣除余额
         * 定义两阶段提交
         * name = reduceStock 为一阶段try方法
         * commitMethod = commitTcc 为二阶段确认方法
         * rollbackMethod = cancel 为二阶段取消方法
         * BusinessActionContextParameter注解 递参数到二阶段方法中
         *
         * @param userId 用户ID
         * @param money  扣减金额
         */
        @TwoPhaseBusinessAction(name = "reduceBalance", commitMethod = "commitTcc", rollbackMethod = "cancelTcc")
        void reduceBalance(@BusinessActionContextParameter(paramName = "userId") Integer userId,
                           @BusinessActionContextParameter(paramName = "money") BigDecimal money);
    
        /**
         * 确认方法、可以另命名,但要保证与@TwoPhaseBusinessAction中 commitMethod一致
         * context可以传递try方法的参数
         *
         * @param context 上下文
         * @return boolean
         */
        boolean commitTcc(BusinessActionContext context);
    
        /**
         * 二阶段取消方法
         *
         * @param context 上下文
         * @return boolean
         */
        boolean cancelTcc(BusinessActionContext context);
    
    }
    
  3. 业务实现

    
    import com.baomidou.dynamic.datasource.annotation.DS;
    import com.bjpowernode.mapper.AccountMapper;
    import com.bjpowernode.model.Account;
    import com.bjpowernode.service.AccountService;
    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 java.math.BigDecimal;
    
    @Slf4j
    @Service
    public class AccountServiceImpl implements AccountService {
    
        @Autowired
        private AccountMapper accountMapper;
    
        @Override
        public void reduceBalance(Integer userId, BigDecimal money) {
            log.info("当前 XID: {}", RootContext.getXID());
    		// TODO 实际业务逻辑,未发生异常走commitMethod 方法,异常走rollbackMethod 
            
        }
    
        /**
         * tcc服务(confirm)方法
         * 可以空确认
         *
         * @param context 上下文
         * @return boolean
         */
        @Override
        public boolean commitTcc(BusinessActionContext context) {
            log.info("Confirm阶段,AccountServiceImpl, commitTcc --> xid = {}", context.getXid() + ", commitTcc提交成功");
            return true;
        }
    
        /**
         * tcc服务(cancel)方法
         *
         * @param context 上下文
         * @return boolean
         */
        @DS(value = "account-ds")
        @Override
        public boolean cancelTcc(BusinessActionContext context) {
            log.info("Cancel阶段,AccountServiceImpl, cancelTcc --> xid = " + context.getXid() + ", cancelTcc提交失败");
            //TODO 这里可以实现中间件、非关系型数据库的回滚操作
    
            return true;
        }
    }
    
  4. 业务调用

    @GlobalTransactional //seata全局事务注解, TM 事务发起方
    public Integer createOrder(Integer userId, BigDecimal money) throws Exception {
        // 减余额
        accountService.reduceBalance(userId, money);
        // 其他业务逻辑,业务逻辑中某一个步骤发生异常触发全部回滚
        return 123;
    }
    
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值