今天分享微服务项目中一个容易被忽略的分布式事务问题,这是在和第三方服务对接时产生
前言:现有A B两个服务,以及第三方系统C,调用流程如下
A服务接口:
- 数据校验
- 调用B服务
- 根据B服务调用结果 写表
B服务对应接口:
- 数据校验
- 调用 第三方C服务(C服务这个接口也是带有 修改属性的接口)
- 根据结果 写表
注:自身系统A、B服务与第三方系统数据一致性如何保证暂不在本文讨论范围内
现有配置:
自身项目服务内读超时时间为10s,而第三方服务不是很稳定,所以Feign给配置的读超时时间为60s[第三方C服务稳定时响应时间在200ms]
结合上述流程,问题就来了,如果B服务调用第三方C服务,时间超过了10s,这个时候A服务会抛出读超时异常并回滚本地事务,但此时B服务还是在阻塞等待第三方C响应,如果C响应成功,那么最终B服务会去写表记录数据,从而导致A B服务数据不一致
这个时候有朋友就说了,使用分布式事务框架不就可以解决A B服务数据不一致的情况吗?
这里考虑两点:
- 已知分布式事务无论是2PC/3PC/TCC/本地消息表/MQ事务消息等等方案都会对性能造成一定影响
- 第三方C服务不一定会提供数据回滚接口,那这时分布式事务框架也无能为力了
- 业务真的需要实时一致性吗?作为业务当事人的我清楚知道这个业务并不需要保证强一致,只需要在出现异常的情况下,调用方发起重试时能保证最终成功即可
那要如何解决呢?
综合上述其实A B服务数据不一致这个场景是没有必要去使用分布式事务框架的,在B服务接口加一层验证:
- 数据校验
- 判断此数据是否已处理完毕,处理完毕则直接将A服务所需数据返回,反之则继续下面的流程
- 调用 第三方C服务
这样就算在异常情况下A服务超时异常了,当第二次重试请求进来时,A检测到自己未处理完毕会继续调用B服务,而B服务检测到自己已处理成功了会直接返回,A就能根据返回数据继续处理下面流程
而且我们并没有使用分布式事务框架,只是稍微改变了一下业务流程