同步机制应该遵循哪些基本准则|多节点数据来回错乱拖慢了业务

同步机制应该遵循哪些基本准则|多节点数据来回错乱拖慢了业务

那次对接跨系统的对接项目,会议上被反复问到同步机制应该遵循哪些基本准则,我一时答不上来,只知道眼前这套跑起来总出问题。数据在两个系统之间来回传递,有时候更新完这边,那边没收到,隔半小时又突然冒出来一条旧记录,业务同事在后台翻记录,一会看到新数据一会又跳回老版本,已经连续两天在群里发截图吐槽。

最开始想的简单,只要定时拉取数据,定时推送,两边就能对上。把同步任务设置成每五分钟跑一次,脚本写好丢到服务器上,上线第一天看着日志正常,没报错,以为这事就稳了。没过半天,就出现重复写入的情况,同一条订单,在下游系统生成了三条一模一样的记录,业务那边录入人员不得不手动删掉多余条目,删的时候又不小心误删了一条有效数据,后续核对订单花了整整一下午。

以为只是定时任务间隔太短,改成十分钟一次。

问题并没有消失,只是发作的时间拉长了。有次上游系统突然卡顿,提交的变更卡在队列里,等上游恢复之后,积压的批量消息一股脑推向下游。下游接收处理的顺序乱掉,后发生的变更先落地,更早的更新反而晚到,最终保存的是过时信息。业务查单的时候,看到的状态和真实发生的流程完全颠倒,谁也说不清到底哪一条才是真实有效的状态。当时盯着日志滚动,一条条看消息的时间戳,越看越头疼,分不清到底哪里出了断层。

中间也试过,在每次同步之前先比对两边的版本号,版本不一样才执行更新。改完上线,短暂安稳了两天。直到碰到网络抖动,消息发送成功,下游完成数据写入,但是回执信息丢了。上游这边没有收到确认,反复重试推送,版本号判断逻辑被反复触发,又造成数据来回覆盖。有时候下游已经更新完毕,上游还在不断重试,把已经是最新的数据又用旧值覆盖回去,来回拉扯,根本停不住。

团队里另一个同事,负责别的模块同步,他那边采用的是完全不一样的方式,不会主动轮询拉取,只靠事件触发。他说他那边很少出现重复数据,但是一旦消息丢失,不会自动重试,只能人工排查补数据。听他说完,心里更乱,原来不同的做法,踩的坑也完全不一样,不存在一种方式可以适配所有场景。

那段时间天天守着监控面板,盯着同步失败的告警,出现异常就要临时介入处理。有时候是主键冲突,有时候是字段类型不匹配,上游新增字段之后,下游没有同步调整,消息直接丢弃,这类隐性问题不会触发明显报错,要等业务发现数据缺失,才能追溯到源头。每次调整代码,都担心改动之后,引出别的连锁问题,不敢一次性大面积修改,只能一点点试,每次改动之后都要盯着运行状态很久。

试过限制消息的处理顺序,给每条变更带上唯一标识,用来过滤掉已经处理过的消息。调整之后重复写入的情况少了很多,但还是没法处理网络中断、服务宕机这类极端场景。某次上游服务重启,部分未投递的事件直接丢失,下游系统一直保持旧状态,等业务发现差异的时候,已经积累了上百条未同步记录,只能导出两边全量数据做对比,人工补齐差异,工作量大的吓人。

仅代表我个人当时遇到的情况,不同业务场景、不同系统架构下的体验会存在差异。

到项目收尾,这套同步链路依旧没能做到完全不出错,只能依靠定时全量校验兜底,一旦校验发现不一致,就标记出来交给人工核对。没有找到能一次性根除所有异常的手段,每次修复一个问题,总会在某个角落藏着新的隐患。下班收拾电脑的时候,屏幕还留着两边数据对比的表格,密密麻麻的差异行,看着就觉得疲惫。