尧图网站设计 尧图网站设计YAOTU DESIGN
ARTICLE DETAIL

资讯详情

深耕网站设计与一线实操的经验洞察。

系统迁移的并行转换策略:数据同步、双写与对账实践

系统迁移的并行转换策略:数据同步、双写与对账实践 开头干了十来年系统迁移我最怕听到的一句话不是“系统出故障了”而是“我们直接把旧系统停了吧”。说这话的人往往没经历过数据对不平的深夜、回不去旧版本的焦虑、业务方拿着Excel来找你对数的绝望。系统切换这件事本质上是风险控制不是技术表演。今天想聊的并行转换是系统切换里最“稳”但也最难做的一种方式。核心思路很朴素新旧系统同时运行一段时间业务照常跑后台两条腿走路等新系统被验证足够可靠了再让旧系统退休。我做过几回类似的迁移也见过别人做砸的把里面的门道、坑、实操细节整理出来希望能给正在做系统切换的朋友一点参考。这篇文章适合谁看正在规划核心系统迁移的架构师、负责数据迁移的工程师、以及被业务方追问“新系统到底什么时候能上”的项目负责人。全文不绕弯子直接讲方案怎么设计、代码怎么落地、故障怎么排查你可以当一份实操笔记来读。1. 并行转换的设计思路——为什么它是“重武器”而不是“常规选项”1.1 并行和老少切换解决的是同一个问题系统切换的三种常见方式直接切换也叫冷切换选一个切换窗口把新旧系统一次性割接、逐步转换也叫试点切换按区域、按用户分批次迁过去、并行转换新旧系统并行运行一段时间再完成切换。直接切换听着最省事但前提是你能接受最高风险——切换窗口之后旧系统基本就废了新系统出任何问题你连退路都没有。逐步转换相比直接切换灵活一些适用于用户群体可以分批切割的场景。而并行转换正好卡在中间不追求一次性到位也不要求用户分批而是用一个“新旧共存”的过渡期来换取确定性。我见过一个很典型的失败案例某企业上财务系统选了周末直接切换结果新系统生成的报表跟旧系统对不上周一业务方直接炸锅最后只能把旧系统重新启起来账目乱了一周。如果当时用并行转换哪怕新旧系统不一致至少旧系统还能兜底不至于影响核心业务。1.2 并行转换的运作模式——两条腿走路但不是各跑各的并行转换的典型运行方式长这样新旧系统同时对外提供服务新系统通过程序拉取旧系统里的新增数据两边同步跑定期做数据比对确认长跑数据是否一致。等到新旧两边跑出来的结果“对齐”了再把流量切到新系统停掉旧系统。关键点在于“同时运行”的方式有三种串行回放把旧系统产生的数据和操作按顺序在新系统里“重放”一遍验证新系统的处理逻辑。适合业务流程是可回放的场景比如订单处理、审批流。双写模式业务写入时同时写入新旧两套存储或通过消息队列双发保证两边数据源都更新。适合对数据实时性要求高的场景。影子模式流量只走旧系统同时把流量复制一份到新系统新系统只读不写专门观察新系统的处理结果是否与旧系统一致。影子模式风险最小但无法验证用户真实验证场景下的性能和交互。选择哪种模式取决于业务对数据一致性的容忍度。1.3 并行转换真正适合的场景——数据准确性要求高才是它的主场并行转换的核心价值不是“快”而是“稳”。它最适合三类场景财务、交易、合规数据迁移这类数据一旦出偏差就是真金白银的损失。并行期内哪怕新系统算的账跟旧系统差一分钱也能在切割前发现并修正。用户体量大、无法停机的业务像支付、电商促销场景根本不可能给你一个安静的停机窗口。新系统架构变动剧烈比如从单体拆微服务、从自建机房上云数据库结构都换了需要时间让新旧系统各自跑一跑暴露潜在问题。反过来如果你的业务可以忍受离线几小时、用户量也不大或者团队人手根本撑不住两套系统同时运维那并行转换反而会拖垮你。它是重武器杀鸡用牛刀是自找麻烦。2. 核心环节拆解——数据同步、核对与双写一条都不能省2.1 数据同步方案怎么选——CDC、消息双发、定时批同步并行转换对数据同步的要求比普通的数据迁移高一个量级——不只是“搬过去”而是要“持续性、低延迟、可校验”地搬过去。我常用的三种方案方案原理适用场景风险点CDC变更数据捕获监听旧系统数据库的binlog/WAL日志把增删改操作解析出来同步到新系统数据库结构相近、业务强一致要求需要开启数据库日志对性能有损耗解析复杂字段映射要仔细消息队列双发业务代码在写旧库的同时发一条消息到MQ由消费者写入新库新旧系统数据模型差异大需要业务层转换会侵入业务代码双发失败率直接决定一致性效果定时批同步每隔一段时间比如每5分钟、每1小时把旧系统的新数据导出导入到新系统对实时性要求不高、数据量可控延迟高需要确保批次的幂等性如果让我给新手一个组合建议优先用CDC 定时全量对账。CDC管实时增量定时对账管最终一致两者结合才能保证并行转换的核心——数据准确。2.2 数据比对与校验机制——不一致不能靠“感觉”要能自动揪出来并行转换最耗时间的一个环节就是对账。纯手工对数你会发现两个问题第一真的对不完第二对完之后你也不知道该信谁。对账机制的设计要注意三个层次字段级对比针对核心表比如订单、账户、流水选择若干关键字段做全量对比用MD5或哈希值做指纹匹配速度会快很多。汇总级对比每一天跑一个汇总对比新旧系统的总金额、总笔数、差异阈值。差异在阈值内视为正常超了立刻报警。差异原因追踪分布到每一笔差异的根因是同步延迟、程序bug、还是双写丢失我在实操中遇到过一个很矛盾的场景订单表两边字段明明一致但每天的汇总对不上最后查出来是新系统对时区的处理跟旧系统不同午夜12点前后订单被归到了不同的日期。如果只看字段对比永远发现不了。所以对账逻辑里“业务口径对比”一定要有不能只做技术比对。提示对账脚本的核心是“可追溯”。每次对账结果必须留档能回溯到某一笔具体数据的同步日志。不然你和业务方争论“到底谁对”的时候拿不出证据项目就会被卡死。2.3 双写模式的一致性问题——不可能原子写入必须设计补偿机制双写模式的痛点在于双写不是原子操作。旧库写成功了新库写失败了新库写成功了旧库写失败了两边都成功了但个别字段因为格式或默认值不同结果不一致。这些问题几乎每天都会发生。所以双写模式下必须配套一个补偿机制。我常用的做法是双写消息里带一个全局唯一ID另外建一张同步记录表记录每一笔写入的“完成状态”。后台起一个定时任务扫出长时间未完成同步的ID重新触发写入或做人工干预。每次对账如果发现差异顺着同步记录表就能定位到失败的环节修复后重放即可。不要幻想双写一次就能完美一致。它的价值在于给你一个“自愈”的基座让不一致可以被发现、被修复而不是靠运气。3. 实操过程——一套可落地的并行转换实施方案以交易系统为例3.1 阶段零并行前的准备清单别急着开跑正式并行之前的准备工作往往决定之后的成败。别小看这一步我见过最典型的问题就是新旧系统的字段映射表没梳理清楚就开跑结果每次对账都是在填上一个逻辑的坑。准备清单至少包含新旧系统核心数据结构的字段映射表必须逐字段确认含默认值、类型、格式旧系统的数据库日志是否已开启CDC的前提新系统的接口性能基线数据至少要能扛住并行的写入和查询压力明确并行时长的验收标准比如“连续7天数据核对无差异”或“累计对账差异率低于百万分之一”回退预案别等到出问题才去想怎么退还有一个容易遗漏的点业务方的参与确认。并行期间业务方的“最终答案以谁为准”必须提前约定并落到文档里。不然两边系统跑出来的数据不一样销售来问你对谁的账是对的你没法回答项目就只能停摆。3.2 阶段一搭建数据同步管道先把增量通道跑通以我之前做的一个交易系统迁移为例旧系统是Oracle新系统是MySQL分布式的。技术栈不同字段类型映射和状态机都需要转换。我们定的方案是CDC读取Oracle的归档日志解析成统一的数据变更事件投递到Kafka由消费者按字段映射写入新系统MySQL。搭建时的两个关键点先跑通一个表 别指望一次把库里的100多张表全部接通。选一张核心主表打通全部链路观察数据是否正确、延迟是否可控。单表稳定之后再批量扩展。增量同步的幂等性设计要提前做 Kafka在极端情况下会产生重复消息消费者写入MySQL时必须做幂等防重否则对账又要炸。我习惯在每张表的写入逻辑里加一个基于唯一业务单号的去重判断。这一步如果只做不做检查会埋下很大的隐患。我实践下来最有效的办法是每张表接通后立刻写一段临时脚本对比增量数据的条数和关键字段连续比较1000条错了就当场修正别让差异滚到后面。3.3 阶段二存量数据初始化与全量对账增量管道跑通之后紧接着要做存量数据初始化。这个顺序不能反——如果你先迁存量再搭增量那么从“存量迁移开始”到“增量管道启动”之间的新增数据就会漏掉最后无论如何都对不平。正确的顺序是先启动增量同步管道时刻在监听再挑一个业务低峰期做存量全量迁移存量迁移结束那一刻暂停写入把“存量结束时间点”和“增量开始时间点”对齐再打开业务写入继续增量同步严格来说第3步需要一个对账快照点用一个全局时间戳记录“存量迁移到哪个点了、增量又从哪个点开始”两边不能有缝隙。这个“缝隙”是我见过并行转换数据对不平的最大元凶。存量迁移完成后立刻做一次全量对账。这时候如果差异超过你的容忍阈值停下来查根因先别急着往后面走。3.4 阶段三业务双写与日终对账进入真正的“并行期”当增量通道稳定、存量对账通过后才进入真正的业务双写并行期。此时新旧系统同时跑业务每天定时跑对账持续一段时间。并行期的操作重点有三个每天固定跑一次全量对账或抽样对账输出差异报告日报格式最好固定方便前后比对。对差异分级处理判断差异是 A类严重不一致需要停业务排查、B类中等影响部分数据、还是 C类小问题比如字段格式差异对应不同的处理流程。引入灰度流量并行初期新系统的流量占比可以很低比如1%~5%观察新系统的运行稳定性确认没问题后逐步放大到100%。很多人以为“并行”的意思是流量一开始就新旧各一半这是误区。并行转换的安全感来自**“可控制比例”**你可以让新系统一开始只承担10%的流量稳定之后再升到50%、80%最后再切100%每一步都在可控范围内做验证。关于流量放大的一个判断标准什么时候可以把流量升上去我个人的经验标准是上一档流量至少稳定运行3~5天且每天的对账差异率保持在一个可接受水平之后再考虑升档。如果流量已经压到50%了对账出现偏差不要硬着头皮继续升退回来查问题比切过去再回滚好处理得多。3.5 阶段四切换决策与正式切割怎么才算“稳了”并行期结束不是拍脑袋说“感觉差不多了”就能切。要有一组明确的判定条件最好在项目启动时就跟各方达成共识连续N天我一般建议至少7天日终对账差异率为0或低于容忍阈值新系统的核心业务接口成功率、性能指标达到预设目标双写期间无未完结的A类/B类问题满足以上条件之后再选一个低峰窗口做正式切割将流量全部切换到新系统。切割完成后旧系统不要立刻下线保留一段时间的只读访问和数据备份通常保留1~3个月方便新系统出现重大问题时做数据追溯。之后旧系统再彻底下线归档。注意切割时向外位发布的通知要简单明确“系统已切换至新版本历史数据可在旧系统查询”。业务团队和客服团队要先培训避免用户咨询时说不清楚。正式切割当天我的习惯是安排至少一名核心开发在机房或远程盯完全过程同时准备好一键回退的按钮和脚本。哪怕判定条件全满足也得把回退当“标配”这不是不自信是专业。4. 常见问题与排查技巧实录——那些文档里不会写的东西4.1 数据对账始终差那么几条怎么定位并行转换最折磨人的问题就是对账差了几条一直修不完。我的排查思路按这个顺序来看时间窗——确认差异数据是不是发生在“存量快照点”和“增量启动点”的缝隙里。这个缝隙最容易被忽略。看字段口径——比如时间、金额、状态的字段格式两边是否一致旧系统存“12”新系统存“12.00”表面上一样汇总一对比就不对了。看同步日志——有没有特定时间段的消息丢失比如Kafka消费者挂了重启消息是不是被跳过。看幂等逻辑——重复消费是不是覆盖了正确值。我遇到过最邪门的一次对账差了几百条字段、时间、日志全查了没毛病最后发现是新系统的唯一索引比旧系统多了一个约束导致部分数据写入时被拒收产生了“静默错误”。这类问题没有通用的排查公式只能靠日志一点一点挖但顺序对了效率会高很多。4.2 双写后新旧系统行为不一致业务不知道怎么信谁双写模式下“两边数据不一致”不一定是同步问题也可能是新系统逻辑本身有bug。我在迁移一个订单状态机的时候就发现旧系统允许“已取消”的订单重新被激活新系统不允许。两边对同一笔单的最终状态就产生了差异。这时候不要试图靠数据同步去补偿——是对业务逻辑理解有分歧。正确做法是把逻辑差异单独列成清单找业务方逐一确认确认完后按最终口径统一代码逻辑再重新跑对齐测试。务必要把“技术性不一致”和“业务口径不一致”分开处理。前者靠管道、脚本修后者靠业务决策定。4.3 并行期间业务方突然说“新系统不用了”怎么办这种情况不常见但一旦发生就是大项目。通常原因是业务方觉得新系统不好用或与预期差距太大。通用处理原则是先保障业务连续再论证技术方案。旧系统如果还能正常跑就保留旧系统模式停止新系统流量将并行切换改为先行验证模式——继续用新系统做后台影子运行收集数据给业务方看实际效果而不是急着推进度。不要在这种时候强行辩解说“新系统没问题”业务方如果对系统没信心切换成功也会留下后遗症。4.4 回退预案怎么做才真正可用很多项目的回退预案写得好看真到要回退的时候十几个人按半天按钮也没退回去。原因就是预案没有演练过。我的建议回退脚本要定期演练至少演练一次确保脚本在真实数据环境下可用。回退要快决定回退后内部指标建议是30分钟内完成流量回切。回退期间允许数据不一致回退期间的口径是“保业务、保可用”一致性留到事后补。别指望回退还能保持完美一致这不现实。4.5 并行转换检查清单——每次切换前过一遍整理一份我在项目里多次迭代过的检查清单新旧系统字段映射表是否已冻结并评审增量同步管道压测是否达标延迟是否在可接受范围存量迁移快照点与增量启点是否已对齐有无缝隙日终对账脚本是否已自动化差异告警是否有人盯业务口径差异清单是否已确认回退演练是否已执行过EOP脚本是否就绪业务方是否已书面确认并行期结束的验收标准结尾做系统迁移这件事十个项目九个难在“切换那一刻的勇气”而并行转换就是想用日常的麻烦换掉那一刻的惊险。我个人体会最深的一点是不要省掉任何一次对账不要嫌日报麻烦不要觉得回退演练浪费时间。很多当初多花的一天最后都相当于救回了一个月的返工。如果你正在准备做并行切换我最后再分享一个实操细节并行期的对账日报尽量设计成“一眼能看出有没有异常”的排版只留三块——总览指标、差异明细表、需要业务方处理的问题列表。别搞一大串的技术数据业务方不看团队自己看着也累。格式简洁、问题聚焦各方协作的效率会明显不一样。这个内容后续还可以继续扩展的方向比如并行转换结合灰度发布的完整落地方案、CDC同步组件的选型与调优、切换后旧系统的归档策略。有机会我再逐个写开来也欢迎有类似经验的朋友一起交流。迁移这条路稳字当头稳到最后你就知道当初选并行转换这一步值了。
返回列表