转账接口返回成功后前端立刻刷新,余额显示扣了 500 对方却没到账。两秒后再刷又正常,客服一天收到十几条同样的反馈。碰到这种情况,我一般先确认改动有没有真的生效。
原因不复杂,扣款和入账分属两个库,各自提交本地事务,中间有几百毫秒两边不一致。查询接口直接读各自的库,没有过滤处理中的转账单,前端把中间态当成了最终结果。
「跨库转账中间态」相关的日志我一般连着看前后五分钟,单看一条报错经常判断不出是哪一步失败。改完顺手把文档补一句,省得下次自己重新推一遍。
SELECT transfer_no, status, from_acct, to_acct FROM transfer_order WHERE status = 'PENDING' AND create_time < NOW() - INTERVAL 5 MINUTE;
具体做法是,转账单落一条 PENDING 到 SUCCESS 的状态记录;查询余额时把处理中的转账单算进去 或者读快照;前端转账成功后不要立刻拉余额 改为轮询转账单状态;入账失败的单进补偿队列 由定时任务重试。
最后用这个标准收尾,转账成功后查询余额看到的是最终值 超过五分钟还在 PENDING 的单会被补偿任务捞出来。
