seata 全局事务回滚报Failed to report global rollback

73 阅读1分钟

代码逻辑

医嘱收费使用的是seata at 模式编程式事务,伪代码如下

    开启全局事务
    try{
        住院患者扣费并保存费用信息;
        调用药房服务锁库存(rest接口);
        更新医嘱状态;
        全局事务提交;
    }catch(Exception e){
        try{
          全局事务回滚;
        }catch(Exception ex){
        
        }
      
        记录失败信息到医嘱的remark字段;
    }

现象

最近线上经常出现全局事务回滚失败,导致费用多收;

分析

查看日志发现全局事务回滚时,报以下异常: Failed to report global rollback [10.233.88.14:8091:622424281111912448],Retry Countdown: 5, reason: RPC timeout

image.png

通过查看源码发现,tm提交回滚时默认会重试5次,5次都失败后抛出异常

image.png

因为回滚失败后,会更新医嘱数据,导致分支事务回滚时,数据库的数据和undolog的后快照不一致,导致回滚一直失败;

image.png

解决办法

事务回滚失败后不更新源数据,而是新建一个记录表,记录失败原因,避免修改数据导致seata回滚失败