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

资讯详情

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

不停机迁移:双写、回放与最终切换设计——在线交易系统的业务连续性与回退实战

不停机迁移:双写、回放与最终切换设计——在线交易系统的业务连续性与回退实战 文章目录每日一句正能量1. 背景与问题所谓“不停机”不是两个数据库一直同时写2. 环境与数据先确认“可同步”再谈“双写”2.1 兼容评估首先确认KFS同步组合2.2 还要评估“哪些数据不能简单日志回放”2.3 “双写”必须先分类方式A应用同步双写方式BOutbox / 事件双写方式C数据库日志 CDC / KFS方式D切换后目标反向回源3. 复现过程为什么“应用双写成功率99.99%”仍然不够3.1 源成功、目标失败3.2 目标成功但应用认为失败3.3 乱序比重复更隐蔽3.4 全量与增量交界会出现重复或漏数4. 方案实施七阶段不停机迁移设计4.1 阶段一源库仍是唯一主写4.2 阶段二建立全量基线4.3 阶段三KFS持续追平4.4 阶段四影子读与双读验证4.5 阶段五切换前数据一致性验证4.6 阶段六最终冻结和主写权转移S0 SOURCE_PRIMARYS1 READYS2 FREEZES3 FINAL_CATCHUPS4 TARGET_PRIMARYS5 OBSERVATION4.7 Outbox用于补充不可可靠CDC的业务链路4.8 回放必须幂等4.9 回放必须防旧版本覆盖4.10 主键生成权必须在切换点一并转移5. 结果对比不停机迁移真正降低的是“写冻结窗口”不是迁移总时长5.1 传统离线5.2 在线方案5.3 双写方式对比5.4 数据验证5.5 并发/故障注入5.6 示例门禁6. 风险与复盘不停机迁移最大的敌人是“两个主写都觉得自己是对的”6.1 风险一长期同步双写6.2 风险二切换时还有隐藏写入口6.3 风险三目标触发器造成重复副作用6.4 风险四回放幂等只靠主键6.5 风险五无主键表6.6 风险六大事务拖延最终追平6.7 风险七目标切换后立刻销毁源端回退方案先回答“KingbaseES主写窗口的新数据怎么回源”回退触发条件最晚回退截止时间回退时的主键问题最终复盘附录 A主写状态机附录 BOutbox最小字段附录 C最低故障注入附录 D最低切换门禁每日一句正能量人生不是一场必须齐头并进的赛跑而是一片万物自由生长的原野。赛跑有统一的终点和规则令人焦虑原野却允许万物按自己的节律生长——有人是三月桃花有人是九月秋菊各有其时。当我们真正把生命看作原野就会从“落后于他人”的焦虑中解脱。野草有野草的坚韧乔木有乔木的担当花朵按自己的时节开放。主题业务连续性 / 在线交易系统 / 不停机迁移重点双写模式、全量基线、增量回放、KFS 追平、幂等、切换状态机、数据校验与反向回退适用场景订单、支付、会员、账户、交易流水等不能接受长时间停机的核心在线业务。1. 背景与问题所谓“不停机”不是两个数据库一直同时写很多团队第一次设计在线迁移会画出这样一张图应用 ├─写源数据库 └─写KingbaseES然后把它叫“双写不停机迁移”问题是两个独立数据库通常不共享同一个本地事务。如果业务请求源库 COMMIT 成功 目标库连接超时系统到底应该返回成功 失败 重试如果返回失败客户端重试源库已经有一笔 目标可能没有如果返回成功目标差异什么时候补所以真正的“不停机迁移”不是“每个请求同步写两个数据库”而是业务始终有唯一主写数据库同时把已经提交的业务事实可靠地回放到目标当目标完全追平并验证通过后再在一个极短窗口中转移主写权。KingbaseES 官方异构迁移指南明确区分离线和在线迁移在线迁移是在源业务持续提供服务时完成数据搬迁官方提供 KDTS 和 KFS其中 KFS 用于初始搬迁之后的数据实时同步。Kingbase FlySync 官方“不停机迁移方案”也把过程拆成结构迁移 存量数据迁移 增量数据同步 数据一致性验证 业务切换这正好说明业务切换不是迁移第一步而是最后一步。本文采用的总原则迁移前 源数据库唯一主写 迁移中 源数据库唯一主写 KingbaseES持续接收全量增量 最终切换 短暂停写 追平最后水位 验证 转移主写权 切换后 KingbaseES唯一主写 源库保留只读/回退能力2. 环境与数据先确认“可同步”再谈“双写”示例环境源数据库 MySQL 8 / SQL Server / Oracle 中的一种 目标 KingbaseES V9 业务 订单交易系统 日交易 3000万笔 峰值 8000 TPS 数据量 12 TB 最大表 12亿行 迁移 KDTS/Loader全量 KFS增量同步 允许最终写冻结 30~60分钟 回退RTO 20分钟2.1 兼容评估首先确认KFS同步组合KFS 官方部署前评估指南明确要求确认源数据库版本 目标数据库版本 同步组合因为实际版本如果和项目早期沟通版本不一致可能出现部署后不能运行的问题。因此迁移方案中要固定source_db source_version target_version KFS_version driver_version compatibility_mode不要只写MySQL → KingbaseES2.2 还要评估“哪些数据不能简单日志回放”典型风险LOB 大事务 DDL 无主键表 分区变化 字符集 JSON 自增/序列 触发器 级联操作另外如果目标已经开启业务触发器而 KFS 回放的源端事务又触发目标业务逻辑可能发生重复审计 重复消息 重复派生数据所以目标环境在迁移阶段要明确哪些触发器启用 哪些任务暂停 哪些派生逻辑由源端结果同步 哪些由目标重新计算2.3 “双写”必须先分类本文把双写分成四类方式A应用同步双写写源 → 写目标 → 返回优点实现直观缺点半成功 超时 重试 顺序 连接池 事务边界非常难处理。对于核心交易不建议作为默认方案方式BOutbox / 事件双写同一个源数据库事务UPDATE business INSERT migration_outbox提交。消费者异步把outbox应用到 KingbaseES。优点业务事实和事件记录同事务 可重放 可审计这是应用层比较可靠的双写模式。方式C数据库日志 CDC / KFS应用只写源库KFS读取提交日志 → 回放目标优点业务代码侵入小适合异构数据库迁移。方式D切换后目标反向回源只用于回退观察窗口不是长期双主。因为双向同时主写会引入环路 冲突 主键生成权 版本覆盖等问题。3. 复现过程为什么“应用双写成功率99.99%”仍然不够3.1 源成功、目标失败伪代码source.insert(order);target.insert(order);returnsuccess;如果source成功 target超时应用捕获异常return failure客户端重试。这时源库可能订单已经存在如果没有request_id order_no event_id幂等约束就会产生重复订单。3.2 目标成功但应用认为失败目标数据库COMMIT完成但网络返回丢失。应用看到timeout再次回放。所以回放链路必须默认同一个事件可能被执行多次。正确语义不是exactly once delivery而是at-least-once delivery idempotent apply3.3 乱序比重复更隐蔽订单version 10 CREATED version 11 PAID version 12 SHIPPED由于重试或分区12 先到目标 11 后到目标如果UPDATEorderSETstatus:status;最终状态可能PAID发生倒退。所以数据回放不仅需要event_id 去重还需要version_no / source commit sequence控制顺序。3.4 全量与增量交界会出现重复或漏数假设全量快照时间T0KFS 增量从T0之前开始会重复回放。从T0之后太晚开始会漏事务。Kingbase FlySync MySQL 不停机迁移文档明确强调存量数据迁移的关键点之一就是获取日志偏移量该位置用于确定增量数据的起始点。这说明全量快照和增量起点必须是同一个一致性边界。4. 方案实施七阶段不停机迁移设计4.1 阶段一源库仍是唯一主写状态Source: READ WRITE KingbaseES: NO BUSINESS WRITE目标允许DDL部署 全量导入 KFS应用 校验 影子查询但不允许用户业务独立写。这条规则非常重要迁移期间只有一个权威主写。4.2 阶段二建立全量基线执行结构迁移 ↓ 记录源日志水位 ↓ 存量数据搬迁 ↓ 目标索引/统计信息全量期间源业务继续写。这些变化由KFS日志持续记录等全量结束后开始/继续增量应用4.3 阶段三KFS持续追平目标source position ≈ target applied position官方不停机迁移文档通过appliedLastSeqno appliedLatency等状态判断追平情况。实际项目建议额外监控pending_tx pending_bytes oldest_pending_age apply_tps error_tx不能只看延迟秒数4.4 阶段四影子读与双读验证应用主流量仍读源库抽取1% 5% 10%请求在后台同步查询 KingbaseES。比较row count 业务字段 排序 聚合 错误码 P95但KingbaseES结果不直接返回用户这叫Shadow Read优点是在没有用户风险的情况下积累真实SQL和数据验证4.5 阶段五切换前数据一致性验证KFS 官方不停机迁移方案提供数据比对能力包括精简模式 详细模式 差异校验 无缝校验其中无缝校验针对源端业务仍在运行时普通比较可能产生的假差异。切换前建议执行关键表COUNT 分桶Checksum 关键金额 PK/UK 状态分布 最新水位 近期1小时增量门禁P0/P1未解释差异04.6 阶段六最终冻结和主写权转移状态机建议S0 SOURCE_PRIMARY源写ON 目标写OFFS1 READY满足全量完成 KFS稳定 延迟达标 数据校验通过 应用回归通过S2 FREEZE关闭API写入口 MQ消费写入 批处理 定时任务 人工后台写然后等待源端在途事务结束这一步不能只关闭Web API因为后台任务也可能继续写。S3 FINAL_CATCHUP记录final_source_watermark等待target_applied_watermark final_source_watermark并pending_tx0执行最后快速校验。S4 TARGET_PRIMARY切JDBC URL 数据库路由 服务发现 数据库代理KingbaseESWRITE ON源端WRITE OFF READ ONLY注意顺序先确认源写已停止 再开放目标写不要同时存在两个主写S5 OBSERVATION业务已经运行在目标。但源库不要立即销毁保留只读 日志 备份 同步能力 回退脚本直到观察窗口结束。KingbaseES 官方异构移植指南甚至单独列出割接后需要双轨运行这一能力章节。4.7 Outbox用于补充不可可靠CDC的业务链路有些业务事件不仅落数据库DB MQ 搜索 缓存数据库 CDC 只能同步数据库事实不能保证 MQ 副作用已经正确补到目标环境。此时可以增加migration_outbox在同一个源事务记录event_id aggregate_id event_type payload version_no切换或回退时可按event_id重放4.8 回放必须幂等目标建立migration_event_ledger(event_idPRIMARYKEY)每次回放BEGIN 尝试登记event_id 如果已存在 直接跳过 否则 更新业务数据 COMMIT如果业务表有order_no UNIQUE还可以多一层业务幂等。4.9 回放必须防旧版本覆盖目标更新UPDATEtrade_orderSETstatus:status,version_no:versionWHEREorder_id:idANDversion_no:version;或者 UPSERT 中DO UPDATE WHERE target.version_no excluded.version_no让旧事件即使晚到也不会破坏新状态。4.10 主键生成权必须在切换点一并转移源端使用AUTO_INCREMENT IDENTITY SEQUENCE迁移期间目标只接受源端生成的历史ID不要让目标同时自动产生同一业务空间的新ID。最终切换前MAX(id) 序列/Identity当前值 CDC最后ID全部校准。切换后KingbaseES生成器才成为新权威。5. 结果对比不停机迁移真正降低的是“写冻结窗口”不是迁移总时长5.1 传统离线假设12TB上一篇测算得到全量约20小时 工程预算约25小时离线方案停业务 →搬25小时 →校验 →切换业务不可接受。5.2 在线方案后台全量25小时 KFS追平 影子验证用户业务正常运行真正停写5~30分钟级只用于关写 最后追平 最后校验 主写权切换因此“不停机”更准确地说是把长时间的数据搬迁从业务停机窗口里移出去只保留极短的最终一致性切换窗口。5.3 双写方式对比方案业务侵入半成功风险可重放适合核心迁移应用同步双写高高一般谨慎Outbox中低强推荐KFS/CDC低低强推荐长期双主极高极高复杂不推荐5.4 数据验证至少验证行数 PK/UK 金额 状态 版本号 最后更新时间 最近增量窗口全量验证参考上一篇COUNT → 分桶 → Checksum → PK Diff → 字段 Diff切换窗口只做最后增量范围快速闭合5.5 并发/故障注入不要只做正常路径。必须人为制造目标断网 KFS暂停 重复事件 乱序事件 源端长事务 切换时应用连接未释放 目标切换后写入失败然后验证不会丢交易 不会重复交易 不会出现双主 可以安全重试 可以安全回退5.6 示例门禁KFS延迟 5s pending_tx 0 关键数据差异 0 P0/P1差异 0 核心SQL P95 源端120% 错误率 基线120% 源端在途事务 0 目标生成器已校准 回退脚本 READY这些是示例阈值应按业务 SLA 调整。6. 风险与复盘不停机迁移最大的敌人是“两个主写都觉得自己是对的”6.1 风险一长期同步双写如果应用同时直接写源和目标时间越长越容易遇到半成功 死锁差异 超时差异 重试 顺序差异所以核心交易更推荐源单主写 日志/Outbox回放6.2 风险二切换时还有隐藏写入口常见遗漏定时Job 运维脚本 BI写回 后台管理 MQ消费者 补单程序最终冻结必须有Writer Inventory逐项关闭。6.3 风险三目标触发器造成重复副作用例如源端事务插订单 触发审计KFS已经把订单审计都同步目标。如果目标订单触发器又自动生成一条审计就重复。迁移期间目标触发器策略必须专项验证。6.4 风险四回放幂等只靠主键业务事件同一个request_id可能每次生成不同数据库自增ID。只靠PK无法识别重复。应该使用event_id request_id order_no business_key等真正幂等键。6.5 风险五无主键表日志CDC处理UPDATE DELETE时需要可靠定位目标行。无主键或非唯一条件表风险明显更高应该在评估期补主键/唯一键 或 定义可稳定定位策略6.6 风险六大事务拖延最终追平KFS延迟看起来2秒但源端有一个20分钟长事务尚未提交。冻结后它一提交目标需要大量应用所以切换前还要看long running tx oldest tx transaction size不能只看复制延迟。6.7 风险七目标切换后立刻销毁源端这是典型的“理论一次成功”思路。真正生产迁移应该保留源端数据库 日志 备份 旧连接配置 回退脚本至少覆盖既定观察窗口。回退方案先回答“KingbaseES主写窗口的新数据怎么回源”很多所谓回退方案只有改回连接串这是不够的。因为切到 KingbaseES 后的 15 分钟里可能已经产生8万笔新订单这些数据源库没有。直接改回源库就会丢交易正确流程1. 冻结KingbaseES新写 2. 记录target_final_watermark 3. 提取目标主写窗口的新事务 4. 幂等反向回放源库 5. 校准源端序列/自增 6. 校验交易/金额/消息位点 7. 路由切回源库 8. 源库重新开放写回退触发条件建议关键接口失败 关键交易差异 0 P0数据差异 0 错误率超过阈值 P95/P99明显超标 锁/死锁异常 目标数据库稳定性异常 关键下游消息链路失败最晚回退截止时间如果总维护窗口60分钟 回退预计20分钟那么T40分钟就是最终Go / Rollback Deadline到 T40核心验证仍未通过应该立即回退。不要为了“再看5分钟”把整个窗口拖穿。回退时的主键问题目标切换后KingbaseES生成ID 10001~12000反向回源时保留这些ID然后MySQL AUTO_INCREMENT SQL Server IDENTITY Sequence必须推进到 12000避免恢复主写后撞号。最终复盘不停机迁移最稳妥的设计可以概括为源库单主写 ↓ 全量基线 ↓ KFS/Outbox增量回放 ↓ 目标影子验证 ↓ 数据一致性归零 ↓ 短暂冻结 ↓ 最终追平 ↓ 转移主写权 ↓ 双轨观察 ↓ 结束回退窗口而不是应用长期双写两个数据库如果只记住一句话不停机迁移真正要保证的不是“两边同时有数据”而是任何时刻只有一个明确的主写权威并且所有已经提交的业务事实都可以被幂等、可排序、可审计地回放到另一侧。只要主写权 水位 幂等 版本 回放 回退六件事设计清楚在线交易系统的迁移才真正具备生产可控性。附录 A主写状态机S0 SOURCE_PRIMARY → S1 READY → S2 FREEZE → S3 FINAL_CATCHUP → S4 TARGET_PRIMARY → S5 OBSERVE任何状态不得同时 source_writetrue target_writetrue除非业务已经实现并验证真正的冲突解决协议。附录 BOutbox最小字段event_id aggregate_type aggregate_id event_type payload version_no created_at replay_status附录 C最低故障注入[ ] 目标断网 [ ] KFS停止 [ ] 重复事件 [ ] 乱序事件 [ ] 源长事务 [ ] 目标数据库重启 [ ] 切换后应用错误 [ ] 回退反向回放附录 D最低切换门禁[ ] 全量完成 [ ] KFS ONLINE [ ] KFS延迟达标 [ ] pending_tx0 [ ] 关键数据差异0 [ ] P0/P10 [ ] 源端隐藏写入口已全部盘点 [ ] 目标序列/Identity已校准 [ ] 应用路由切换已演练 [ ] 冒烟脚本已准备 [ ] 反向补偿已准备 [ ] 最晚回退截止时间已确认转载自https://blog.csdn.net/u014727709/article/details/163780622欢迎 点赞✍评论⭐收藏欢迎指正
返回列表