描述:同时变更两个系统,如何保证数据一致
你是否遇到过需要同时修改两个系统的价格、数量的述求,记录一下我最近在开发过程中遇到的类似问题,希望对你有所帮助
一、业务场景
1、物品有一个"销售渠道"的属性,举个例子,这个物品可以在淘宝卖,也可以在拼多多卖,销售渠道枚举大致如下:
TB-淘宝
PDD-拼多多
XHS-小红书
2、物品可以同时在多个渠道销售售卖,如物品A销售渠道为 TB & PDD
3、公司有两个系统存储了物品的销售渠道,举个例子:库存系统保存了物品销售渠道,销售系统也保存了物品销售渠道(原因不展开)
4、述求:上游服务请求库存系统变更销售渠道,库存服务需要变更本地销售渠道,并请求销售系统变更销售渠道
二、问题&难点
如何保证库存系统、销售系统中物品的销售渠道一致(分布式相关问题我这里就不细说了)
三、一种解决思路
粗略解读一下思路
- 首先,库存系统获取销售系统当前的销售渠道,且是带版本号的
- 发起变更销售渠道的请求,入参包含原销售渠道、原销售渠道版本、目标销售渠道、目标销售渠道版本(版本号可以用纳秒时间戳或者UUID,总之,尽可能保证唯一)
- 因为是远程调用,因此可能失败、可能成功、可能超时(网络异常)
- 失败则直接结束流程
- 成功则变更本地数据库销售渠道,若变更本地数据库成功,则结束(这里特别说明下,注意事务的范围,不要给整个流程加事务,事务范围包含本地数据变更的步骤即可)
- 若变更本地数据库失败,则同超时处理逻辑——走回滚流程
- 回滚:以假设已变更销售系统成功的前提发起回滚销售系统的销售渠道,将销售渠道变更回去,不过,要用新的版本号
- 再次发起变更销售渠道请求,销售系统判断当前系统的销售渠道与版本号是否符合,若符合则更新并结束;若不符合则明确告诉调用方,该情况下库存系统视为成功并结束;若该次请求还是超时或发生其他异常,则重试
- 回滚步骤调用销售系统接口时可以采用一些重试组件,同步请求一次后,后续采用异步的方式,直到成功为止,若重试x次依旧失败,则告警出来人为比对&处理,因此也需要提前准备一下后门(避免真发生时无从下手)
- 版本号解决的问题:若图中步骤2超时(实际失败),在步骤3真正执行前,存在另外正常业务发起变更渠道请求(目标同为PDD),然后步骤3发起回滚时将渠道又切回了TB&PDD,覆盖了业务的正常操作数据
该思路是通过尽可能补偿的方式保持最终的一致性
当然异步补偿时可以先将上下文写到本地库,再发起重试请求,避免数据的丢失,这里采用异步补偿的方式主要是为了接口性能考虑,此时应直接响应调用方已失败,自助补偿即可