springcloud分布式事务回滚失败

springcloud分布式事务回滚失败

1.场景还原

 笔者在公司最近的一个项目采用springcloud框架搭建微服务架构,这势必会引发分布式事务处理的思考,目前处理分布式主流方案tcc及消息的最终一致性;今天笔者集成github上较为流行的tx-lcn分布式处理框架,它是基于redis的一种补偿型处理方案

2.实现方案

①先截图,下载该框架

springcloud分布式事务回滚失败_第1张图片从github上的starts数量来看,目前还是较多开发者采用了这种方案的,而且作者维护迭代也很及时

②将tx-manager微服务单独拎出来,集成在自己的项目中

springcloud分布式事务回滚失败_第2张图片将tx-manager中application.properties中的配置改成自己的项目配置

③然后涉及分布式的微服务中添加如下依赖



   com.codingapi
   transaction-springcloud
   ${lcn.last.version}
   
      
         org.slf4j
         *
      
   

 

   com.codingapi
   tx-plugins-db
   ${lcn.last.version}
   
      
         org.slf4j
         *
      
   

④下载tx-demo,参考链接:https://github.com/codingapi/springcloud-lcn-demo

将其中的两个实现类复制到自己工程的service中

springcloud分布式事务回滚失败_第3张图片⑤开启tx-manager,在各个微服务application.yml配置tx-manager地址

# 分布式事物
tm:
  manager:
    url: http://localhost:8899/tx/manager/

3.应用步骤

①分布式事务起始服务方

@Transactional
@TxTransaction(isStart = true)
public int addAcount(String logId){
   int i = yiViUserAccountMapper.increaseAccount("100","71d8beff-9e70-11e7-9a60-00163e0a3457");
 
   int n =  paymentDispatchFeignClient.test(logId); //调用失败
 
   if(n == 0){
       throw new RuntimeException("服务调用失败");
   }
    return i + n;
}

②被调用服务方

@Override
@Transactional
@TxTransaction
public int test(String logId) throws YiViException {
    int i = yiViDispatchOrderStatusLogMapper.deleteByPrimaryKey(logId);
    return i;
}

下面是错误:笔者使用分布式事务时遇到得坑,希望能解决小编得问题,服务A事务执行调用FeignConfiguration方式调用服务B事务,A事务成功回滚数据,B事务执行业务但未回滚且未发现异常错误如下:
1.事务A回滚成功图
springcloud分布式事务回滚失败_第4张图片
2.事务B未执行回滚业务图
springcloud分布式事务回滚失败_第5张图片4.解决问题
先叙述下问题:因为配置文件内加载了rabbit,项目内引用了该配置文件,其中rabbit是链路追踪用于请求跟踪,导致事务A在执行回滚操作时调用事务B的初始化时未将groupId插入RequestTemplate表头内,未调用此方法代码如下:

    @Override
    public void apply(RequestTemplate requestTemplate) {

        TxTransactionLocal txTransactionLocal = TxTransactionLocal.current();
        String groupId = txTransactionLocal == null ? null : txTransactionLocal.getGroupId();
        int maxTimeOut = txTransactionLocal == null ? 0 : txTransactionLocal.getMaxTimeOut();
//        this.logger.info("LCN-SpringCloud TxGroup info -> groupId:" + groupId);
//        RequestAttributes requestAttributes = RequestContextHolder.currentRequestAttributes();
//        HttpServletRequest request = requestAttributes == null ? null : ((ServletRequestAttributes) requestAttributes).getRequest();
//        Object attribute = request.getAttribute("OAuth2AuthenticationDetails.ACCESS_TOKEN_VALUE");
//        String token = attribute == null ? null : attribute.toString();
//        requestTemplate.header("Authorization", "Bearer " + token);

        logger.info("LCN-SpringCloud TxGroup info -> groupId:"+groupId+",maxTimeOut:"+maxTimeOut);

        if (txTransactionLocal != null) {
            requestTemplate.header("tx-group", groupId);
            requestTemplate.header("tx-maxTimeOut", String.valueOf(maxTimeOut));
        }
    }

以至于事务B在执行操作时未能获取到事务组groupId而导致事务B未能回滚。解决办法如下:

    
      
      
    

将配置文件POM.xml注释掉rabbit。重新启动事务回滚成功。

你可能感兴趣的:(springcloud分布式事务回滚失败)