数据一致性方案设计
以B2B电商订单下单场景为例,流程做一定的简化,然后梳理与多个外部系统交互可能带来数据一致性问题的场景,通过最终一致性架构设计给出轻量级解决方案,并梳理出设计要点。
01 前言
对于软件开发来说,绕不开与外围系统的对接,因网络、系统、代码设计等多种不稳定因素,经常出现各种异常情况,结果带来的是系统的不稳定和数据的不一致,在生产环境上,出现类似情况,经常要加班加点人工进行修正处理,是一件非常痛苦的事情。
那么在与外围系统对接过程中,异常避免不了的情况下,我们如何通过前期的设计来减少数据的不一致,本文从最小的成本保证数据一致性的角度来进行架构设计,网上还有很多其他方法,大家按需进行选择!
02 数据一致性场景
用户在商城选购好商品后,进行订单下单流程:
正向流程:
生成订单,同时消耗库存、核销优惠券、使用会员权益、异步发送结算请求、异步发送通知消息。
逆向流程:
业务代码逻辑异常或外部系统调用失败,本地事务回滚,异步定时器回滚库存、优惠券、会员权益;若回滚失败,定时器重试。
03 数据一致性设计
设计要点:
前端用户下单做好防抖处理,后端做好分布式锁,防止同一时间产生多个相同的订单
前端用户可以在下单失败时,可以通过前端 UI 界面再次发起进行前台重试
后端外部系统调用,如果使用 FeignClient,配置FeignClient 重试时,不要进行一刀切的进行重试,按需进行配置,不一定外部系统都做好了幂等,同时做好重试次数约定
和外部系统约定好幂等 key,标记是否是同一次请求,外部系统接收多次相同请求时,返回正常处理结果
可能大部分系统只是提供接口状态查询,不支持幂等,需要调用方先查询,判断是否需要再次重试
分析业务系统对于外部系统调用,是否阻塞主流程、数据一致性业务是否强要求等
外部系统的调用应放在代码逻辑执行的最后,因为远程调用是非常不稳定的,可能因网络抖动、服务异常、代码异常等因素导致调用失败
可异步但是数据一致性非常重要的,比如:财务结算,可以直接插入一条任务数据到任务表,异步执行但是通过定时器保证数据的最终一致性
可异步但是数据一致性要求不高,比如:发送短信通知等,可在事务提交 After Commit 之后,启动一个异步线程去执行
如果涉及一个业务逻辑涉及调用多个同步调用的外部系统,优先将容易出错的放在前面调用,防止总是出现正常调用成功的系统要进行数据的回滚,或者人工处理保证整个流程成功
同步调用的外部系统逻辑,如果出现异常报错,重新启动一个事务,将任务数据进行保存,用于回滚其他调用外部系统成功的数据
启动一个定时器,补偿本地事务失败带来的数据一致性问题
04 附录
核心代码逻辑:
CAP 理论:
BASE 理论:
分布式事务分类:
半消息机制最终一致性: