为什么只剩双写一条路
把几亿行数据从老库搬到新的分片架构,先算时间账:全量拷贝按每小时千万行的安全速率,几天起步;期间线上业务还在持续写入——搬完的那一刻,数据已经过时了几天。停机迁移能终结这个死循环,但业务批不出这个窗口。于是唯一现实的方案浮出水面:老库照常服役,新库并行同步,两边数据追平后灰度切流。这套方案拆成四个阶段:存量同步 → 增量双写 → 全量校验 → 灰度切流,本篇讲前两个,校验与切流留给下一篇。
阶段一:存量同步
存量搬迁的技术选型不重要(dumponly、DataX、自研分批脚本都行),纪律才重要,三条:限速——搬迁查询压在源库安全水位以下(用空闲时段加限速批次,别把主库 IO 打满拖垮线上业务);断点续传——按主键或时间片分批,每批记水位,挂了从水位继续;与新库写入兼容——迁移程序写入新分片时绕过业务逻辑直接落库,但 ID、分片基因必须与线上规则严格一致,否则全量校验一地鸡毛。
阶段二:增量双写
存量在搬,增量在写——双写就是把这段「追赶期」的数据变更同时送达两个库。实现方式两条路,侵入度与可控性各有取舍:业务代码双写——在写路径里同时写老库与新分片,逻辑直白、排查直观,但每个写接口都要改、要防两库写一半(各自的本地事务,失败要靠补偿对账兜),代码侵入大;订阅 binlog 同步——老库仍是唯一写入口,binlog 被订阅程序捕获后转换成新分片的写入,业务代码零改造。binlog 链路天然有序、可靠,代价是多一套同步组件要维护:
业务 ──写入──> 老库(唯一权威) ──binlog──> 订阅同步服务
├─ 解析变更(表/行/操作)
├─ 按分片规则路由到新分片
└─ 写入新库(失败进重试队列)工程里更常见的组合是binlog 同步打底,双写只在关键路径做保险。无论哪种,两条纪律要立住:以老库为权威——双写期间老库的数据永远是基准,新库只许追不许改业务语义;失败只告警不阻塞——新库写失败绝不能影响线上业务,靠重试队列加对账修复,这是双写期间业务零感知的代价交换。
追赶与追平
存量同步与增量双写有个鸡生蛋的先后问题:存量搬了三天,期间的变更怎么办?标准答案是先启增量双写,再跑存量同步——双写把「此刻起」的变更送达新库,存量任务负责「此刻之前」的历史,两条线在时间上无缝衔接;重叠的少数边界数据,靠新库的幂等写入(主键冲突即跳过或覆盖)自然去重。当存量搬迁完成、双写延迟稳定趋近于零,就到了下一阶段:全量校验——数据「看起来追平」和「真的追平」之间,隔着一套严谨的核对体系,下一篇展开。
评论 (0)