【分布式事务TCC模式】 SpringCloud整合Seata框架,实现TCC模式

前言

这篇文章我主要演示在Spring中如何使用seata框架的TCC事务模式,并不会区过深研究TCC的模型,那么还是首先来简单介绍一下什么是TCC

简介

Seata TCC 模式

一个分布式的全局事务,整体是 两阶段提交 的模型。全局事务是由若干分支事务组成的,分支事务要满足 两阶段提交 的模型要求,即需要每个分支事务都具备自己的:

  • 一阶段 prepare 行为
  • 二阶段 commit 或 rollback 行为

有点类似于Java中的try-catch操作,来看下面更好的理解它

  • 一阶段 prepare 行为:调用 自定义 的 prepare 逻辑。
  • 二阶段 commit 行为:调用 自定义 的 commit 逻辑。
  • 二阶段 rollback 行为:调用 自定义 的 rollback 逻辑。

这样看起来就更明白了,所谓 TCC 模式,是指支持把 自定义 的分支事务纳入到全局事务的管理中。

示例

假设我们有一个服务A和服务B,服务A为入口,在服务A的代码逻辑中需要调用服务B的接口,使用TCC的模式来保证他们的事务安全问题。

服务A的Service接口

@LocalTCC
public interface CityTCC extends IService<City> {
    @TwoPhaseBusinessAction(name = "prepare", commitMethod = "commit", rollbackMethod = "rollback")
    void prepare(@BusinessActionContextParameter(paramName = "name") String name,
   				 @BusinessActionContextParameter(paramName = "address") String address);

    boolean commit(BusinessActionContext context);
    
    boolean rollback(BusinessActionContext context);
}
  • @LocalTCC:作用于服务接口上,表示实现该接口的实现类被 seata 来管理,seata 根据事务的状态,自动调用我们定义的方法,如果没问题则调用 Commit 方法,否则调用 Rollback 方法。
  • @TwoPhaseBusinessAction:该注解用在接口的 Try 方法上,name 为 tcc 方法的 bean 名称,需要全局唯一,一般写方法名即可
  • @BusinessActionContextParameter:该注解用来修饰 Try 方法的入参,被修饰的入参可以在 Commit 方法和 Rollback 方法中通过 BusinessActionContext 获取。

服务A接口实现

@Service
@Slf4j
public class CityTCCImpl extends ServiceImpl<CityMapper, City> implements CityTCC {

    @Resource
    private CityMapper cityMapper;
	
    @Resource
    private FeignServiceB serviceB;

    @Override
    @Transactional
    public void prepare(String name, String address) {
    	log.info("执行try操作");
    	//一般为锁定资源阶段,判断资源是否存在,对资源进行修改操作等等...
    	//如果当前try操作没有发生异常,则会执行commit方法体内容
    }

    @Override
    @Transactional
    public boolean commit(BusinessActionContext context) {
    	log.info("执行commit操作");
    	City city = new City();
    	city.setName(context.getActionContext("name"));
        city.setAddress(context.getActionContext("address"));
        
        try{
      		cityMapper.insert(city);
			//调用B服务的方法
			serviceB.addCityArea();
			return true;
		}catch(Exception e){
			return false;
		}

    }

    @Override
    @Transactional
    public boolean rollback(BusinessActionContext context) {
    	//手动执行回滚业务逻辑......比如把已修改的状态在修改回来等,根据你们的需求进行自定义操作
    	log.info("执行rollback操作");

		return true;
    }
}

服务A的接口

@RestController
@RequestMapping("/city")
public class CityController {
    @Resource
    private CityService cityService;

    @RequestMapping("/addCity")
    @GlobalTransactional//在入口函数上添加全局事务管理
    public void tccAddCity(@RequestParam("name")String name,
    						@RequestParam("address")String address) {
        cityService.prepare(name, address);
    }
}

流程讲解

当请求调用服务A的/city/addCity请求时,首先会走到prepare方法中进行操作,如果该方法没有发生异常,则自动走到commit方法中执行,判断最后返回的布尔值是否为true,如果为false则不会进行添加入库操作。

总结

这只是一个简单的TCC模式使用案例,仅供参考如果哪里有问题可以在评论区讨论一下。本篇文章就到这里了,再见啦

你可能感兴趣的:(分布式,spring,cloud,spring)