springcloud分布式事务回滚失败
1.场景还原
笔者在公司最近的一个项目采用springcloud框架搭建微服务架构,这势必会引发分布式事务处理的思考,目前处理分布式主流方案tcc及消息的最终一致性;今天笔者集成github上较为流行的tx-lcn分布式处理框架,它是基于redis的一种补偿型处理方案
2.实现方案
①先截图,下载该框架
从github上的starts数量来看,目前还是较多开发者采用了这种方案的,而且作者维护迭代也很及时
②将tx-manager微服务单独拎出来,集成在自己的项目中
将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中
⑤开启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回滚成功图
2.事务B未执行回滚业务图
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。重新启动事务回滚成功。