订单库多表合并重构:零停机、无感知与数据一致性保障实践

背景:

我们系统有多个订单来源,每个来源单独建表,一共六七张,维护成本高,查询也慢,所以决定合并成一张大订单表。

挑战:

第一不能停机;第二不能影响同事正常开发;第三因为是核心链路,数据必须100%准确;第四多张表ID可能冲突。

解决方案

第一,在DAO层做代理,上游无感知。

我们在MyBatis-Plus的Mapper层加了一层代理,把"写老表还是新表"、"读哪个数据源"这些逻辑全部封装在代理里面。上游Service层代码一行不改,同事完全不知道底层在迁移。这样我们干我们的活,他们写他们的代码,互不干扰。

第二,先双写再灰度切流。

先双写(写操作同时写老表和新表),但读流量还是走老表,观察一阵没问题之后,开始按用户ID取模灰度切读流量,1%→10%→50%→100%,每一步都观察监控,稳了再放量。这样就实现了平滑迁移,不停机。

第三,三层兜底保证数据一致。

一层是双写时,写老表和新表放同一个事务里,要成功一起成功,要挂一起挂。

二层是同步历史数据,增量兜底,针对更新场景,如果新表还没这条数据就插入,有了就更新,同时比对更新时间,只认最新的。

三层是离线对账,每天定时跑任务把新老表数据逐条比对,发现不一致就告警并自动修复。刚开始告警几百条,慢慢越来越少,归零就说明数据稳了。

另外,灰度切流的时候还有一个校验机制:命中的请求读新表的同时,后台异步反读老表做对比,发现不一致就告警但不阻塞用户,相当于在切流过程中加了个探针。

主键ID冲突的问题

多张订单表合并成一张,主键ID可能会打架。比如A表有ID=1的订单,B表也有ID=1的订单,俩数据塞到同一张新表里,主键冲突,直接写不进去。

这块我们比较幸运,系统一开始就没用数据库自增ID,每个订单的流水号全局唯一。所以合并的时候天然没有冲突问题,省了很多事。

如果用的是自增ID,合并前必须处理,常见方案有:

· 给不同表的老数据ID加不同前缀或偏移量,比如A表ID不变,B表所有ID加1000万

· 生成新的全局唯一ID替换老的,同时把新旧ID的映射关系存下来,关联数据一并处理

· 新表不用单一主键,用"来源类型+原ID"作为组合主键

相关推荐
I Am a robert girl10 小时前
从科学代码库到智能体训练场:ScienceIDE 的架构拆解与工程启示
架构·强化学习·代码仓库·科学计算·监督微调·智能体训练·可编程环境
天远Date Lab12 小时前
零信任架构实战:基于天远名下车辆车牌查询A构建自动化社区车位摇号核验网关
运维·人工智能·架构·自动化
代码方舟12 小时前
零信任架构实战:基于天远名下车辆车牌查询A构建自动化机动车辆资产清查网关
大数据·人工智能·架构·自动化
nvd1112 小时前
剖析 LangChain4j 的声明式 Agent 架构:从动态代理到大模型函数回调的底层真相
架构
张彦峰ZYF12 小时前
从智能体到生产系统:企业 Agent 规模化的治理、记忆、知识与安全
人工智能·安全·架构·operatingsystem·agent platform·agentcontrol·agent mesh
Dawson Zhu13 小时前
Multi-Agent架构与适用边界:何时应该使用Multi-Agent架构
人工智能·语言模型·架构·aigc·agi
梦帮科技13 小时前
【3.0修订版】跨链桥架构与资产守恒:BSCBridge、BSCMirrorBridge 与 Lock-and-Mint 模型
架构·去中心化·区块链·智能合约·共识算法·信任链
她的男孩13 小时前
分片上传的大文件人人可下载:文件模块 isPrivate 在合并时被抹成 false,另有 4 个静默坑
java·后端·架构
钱栈up13 小时前
工业时序数据中台架构演进:从 IoTDB + MySQL 到去 DWD 层简化实践
架构
xianghongtao011614 小时前
麦肯锡2026技术趋势04_AI基础设施与模型架构_研究解读
大数据·人工智能·架构