前言
在做订单模块的时候,本地事务中包含了远程调用,引发一些问题,这里做一次简单的复盘。
1、问题复现
首先下完订单,调用支付服务成功,然后支付服务收到微信的回调,然后通知我支付结果
但是我的支付回调模块里面有一些业务逻辑,涉及到本地多个表的插入和修改操作,同时我把远程调用接口也都放到了我这个本地事务里。如下:
代码逻辑
// 支付回调@Transactional(rollbackFor = Exception.class)@Overridepublic RespResult<PatientPayResDTO> payCallBack(PatientPayReqDTO req) {// 1、处理自己本地的逻辑// 2、远程调用一些其他服务接口{// 2.1 通知医生服务扣减库存// 2.2 如果医生没有库存那么进行调用支付服务退款}}
问题描述
我这个方法是一个大事务 @Transactional(rollbackFor = Exception.class),当"1、处理自己本地的逻辑完成" 之后,执行第二步的时候,调用医生服务扣减库存,如果医生没有库存,然后进行退款,此时调用支付服务进行退款。但是支付服务需要订单服务将回调的成功结果返回之后才会进行落库,如果此时发起退款,支付服务是没有完成支付成功的落库,那么就会报错。导致回滚。
代码修改之后逻辑
// 支付回调@Overridepublic RespResult<PatientPayResDTO> payCallBack(PatientPayReqDTO req) {// 1、处理自己本地的逻辑// 2、远程调用一些其他服务接口{// 2.1 通知医生服务扣减库存// 2.2 如果医生没有库存那么进行调用支付服务退款}}@Transactional(rollbackFor = Exception.class)// 1、处理自己本地的逻辑
支付服务也要保证先处理自己的事务。
先完成自己本地事务,然后在进行远程调用,这样来看远程调用是否发生问题和我自身都没有关系,如果因为发出问题,导致数据不一致,我们可以采取一些兜底方式,保证数据最终一致性就好了。
后记
先保证自己,后保证他人