一、DTS 增量同步完成后的流量切换策略
1. 切换期间的数据写入处理
• 场景:DTS 增量同步完成(Lag=0)后,业务流量切换到 PolarDB-X 的瞬间可能产生 2-3 秒延迟,导致部分订单仍写入 MySQL。
• 解决方案:
◦ 双写兜底机制:在切换期间,同时写入 MySQL 和 PolarDB-X,确保数据最终一致性。
◦ 异步补偿写入:通过消息队列(如 Kafka)将 MySQL 的写入操作异步同步到 PolarDB-X。
// 示例:双写逻辑(切换期间)
public void saveOrder(Order order) {
// 写入 MySQL(过渡期兜底)
mysqlRepository.save(order);
// 异步写入 PolarDB-X(通过消息队列)
messageQueue.send(“polardbx_write”, order);
}
• 数据校验:在 PolarDB-X 侧增加 数据比对服务,检测 MySQL 与 PolarDB-X 的差异并自动修复。
2. 延迟订单的处理
• 自动重试:若订单写入 MySQL 后未及时同步到 PolarDB-X,通过 重试机制(如指数退避)重新写入 PolarDB-X。
• 人工干预:设置监控告警,对延迟超过阈值的订单进行人工核查和补录。
二、部分流量切换到 PolarDB-X 时的数据一致性方案
1. 分批次流量切换
• 灰度策略:按用户 ID、订单类型等维度逐步切换流量,避免全量切换风险。
• 示例代码(基于 Spring Cloud Gateway):
@Bean
public RouteLocator customRouteLocator(RouteLocatorBuilder builder) {
return builder.routes()
.route(“polardbx_route”, r -> r.path(“/order/“)
.filters(f -> f.setPath(”/polardbx-order"))
.uri(“lb://polardbx-service”)) // 10% 流量切到 PolarDB-X
.route(“mysql_route”, r -> r.path("/order/”)
.filters(f -> f.setPath(“/mysql-order”))
.uri(“lb://mysql-service”)) // 90% 流量仍走 MySQL
.build();
}
2. 剩余 MySQL 写入数据的处理
• 持续同步:保持 DTS 增量任务运行,将 MySQL 剩余写入同步到 PolarDB-X。
• 最终一致性保障:
◦ 定时任务补录:定期扫描 MySQL 中未被同步的订单,批量写入 PolarDB-X。
◦ 业务补偿:在订单支付成功后,强制校验 PolarDB-X 的数据完整性。
三、关键流程图
DTS->>MySQL: 增量同步完成(Lag=0)
App->>MySQL: 写入订单(灰度切换期间)
MySQL->>DTS: 增量日志
DTS->>PolarDBX: 同步增量数据(延迟2-3秒)
App->>PolarDBX: 直接写入(非灰度流量)
PolarDBX->>PolarDBX: 异步补偿写入(MySQL 延迟订单)
Note right of PolarDBX: 数据比对服务检测差异并修复
四、风险控制与监控
风险点 | 解决方案 |
---|---|
延迟订单丢失 | 双写兜底 + 消息队列重试 + 人工补录 |
数据不一致 | DTS 数据校验 + 定时任务补录 + 业务层校验 |
PolarDB-X 写入压力突增 | 限流熔断(如 Sentinel) + 自动扩容 |
DTS 同步延迟 | 监控 Lag 值,超过阈值触发告警并自动扩容 DTS 任务规格 |
五、总结
- 切换期间延迟订单:通过双写和异步补偿确保最终写入 PolarDB-X。
- 部分流量写入 MySQL:持续运行 DTS 同步任务,结合补偿机制处理剩余数据。
- 核心原则:
• 最终一致性:允许短暂延迟,但需保证数据最终同步。
• 可观测性:通过监控和日志实时跟踪数据状态。
• 回滚能力:若切换后异常,快速回滚到 MySQL 双写模式。