代码逻辑
医嘱收费使用的是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
通过查看源码发现,tm提交回滚时默认会重试5次,5次都失败后抛出异常
因为回滚失败后,会更新医嘱数据,导致分支事务回滚时,数据库的数据和undolog的后快照不一致,导致回滚一直失败;
解决办法
事务回滚失败后不更新源数据,而是新建一个记录表,记录失败原因,避免修改数据导致seata回滚失败