4. 迁移流水线总体架构:源数据库、变更捕获、转换引擎、目标数据库、监控与回滚

数据库迁移流水线并非简单的数据搬运工具,而是一个具备可观测性、可逆性、可重复性的工程系统。本章从领域驱动设计的视角,将流水线拆解为五个核心领域:源数据库、变更捕获、转换引擎、目标数据库、监控与回滚。每个领域承担明确的职责,并通过接口契约进行交互。

架构原则:流水线各阶段之间通过不可变事件(Immutable Event)进行通信,确保任意阶段失败时,上下游状态可追溯、可重放。

4.1 五阶段架构总览

下图展示了迁移流水线的完整拓扑结构,数据从左至右流动,控制流与监控流从右至左反馈。

数据库迁移流水线五阶段架构图 迁移流水线五阶段架构 源数据库 MySQL / Oracle / PG 存量 + 增量 变更捕获 CDC / 日志解析 Debezium / Canal 转换引擎 Schema 映射 数据清洗 / 路由 目标数据库 TiDB / ClickHouse 写入 / 校验 监控与回滚 延迟监控 · 数据校验 · 断点续传 · 回滚指令 说明:实线为数据流(Data Flow),虚线为控制/监控流(Control/Monitor Flow)
关键设计决策:监控与回滚作为横向贯穿层,与四个纵向阶段均有交互。这种“十字形”架构确保任何阶段的异常都能被及时捕获并触发回滚动作。

4.2 源数据库领域

源数据库是流水线的起点,负责提供存量数据快照与增量变更日志。该领域需要解决的核心问题包括:

  • 连接管理:维护连接池,支持主从切换、只读实例路由。
  • 快照一致性:通过全局读锁或 MVCC 快照,保证存量数据的一致性视图。
  • 日志保留策略:确保 Binlog / WAL 保留时间足够长,避免增量阶段因日志过期而丢失变更。
源数据库类型 变更捕获方式 快照方式 注意事项
MySQL 5.7+ Binlog ROW 格式 SELECT + 一致性读 binlog_row_image 需设为 FULL
PostgreSQL 10+ Logical Replication Slot pg_dump / COPY 需提前创建 publication
Oracle 12c+ LogMiner / XStream Data Pump / 闪回查询 需开启归档日志与补充日志
MongoDB 4.0+ Change Streams mongodump 需副本集或分片集群

4.3 变更捕获领域

变更捕获(CDC)是流水线的数据感知层。它监听源数据库的变更事件,将其转化为统一的事件格式,并推送到下游。该领域包含两个子阶段:

  1. 日志读取器(Log Reader):从源数据库读取原始变更日志,维护偏移量(Offset)。
  2. 事件转换器(Event Converter):将原始日志转换为标准化的 ChangeEvent 消息。
常见陷阱:CDC 组件必须处理断连恢复场景。如果源数据库发生主从切换,CDC 需要自动重连到新主库,并从上次提交的偏移量继续读取,避免数据重复或丢失。
// 标准化 ChangeEvent 结构(伪代码)
{
  "source": {
    "db": "order_db",
    "table": "orders",
    "server_id": 123,
    "timestamp_ms": 1699000000000
  },
  "before": { "id": 1001, "status": "PENDING", "amount": 299.00 },
  "after":  { "id": 1001, "status": "PAID",   "amount": 299.00 },
  "op": "u",  // c=create, u=update, d=delete, r=snapshot
  "ts_ms": 1699000001000
}

4.4 转换引擎领域

转换引擎是流水线的业务逻辑核心。它接收标准化事件,执行以下操作:

  • Schema 映射:将源表结构映射到目标表结构,处理字段名变更、类型转换、默认值填充。
  • 数据清洗:过滤无效数据、去重、格式标准化。
  • 路由分发:根据业务规则将数据路由到不同的目标表或目标集群。
  • 事务合并:将多个细粒度事件合并为批量写入,提升目标数据库吞吐量。

转换引擎通常采用无状态设计,便于水平扩展。状态(如偏移量、计数器)统一存储在外部中间件(如 Redis 或 ZooKeeper)中。

4.5 目标数据库领域

目标数据库是流水线的终点,负责高效写入与数据校验。该领域需要处理:

能力 说明 实现方式
批量写入 将多条记录合并为一次写入请求 JDBC Batch / 消息队列批量消费
幂等写入 同一事件重复写入不产生重复数据 主键冲突处理 / 事务 ID 去重
写入限流 防止写入过快导致目标库抖动 令牌桶 / 滑动窗口
数据校验 对比源端与目标端的数据一致性 行数校验 / 校验和 / 全量对账

4.6 监控与回滚领域

监控与回滚是流水线的安全保障层。它不直接参与数据流动,但贯穿整个流水线生命周期。核心职责包括:

  • 延迟监控:实时计算源端事件产生时间与目标端写入时间的差值,超过阈值时告警。
  • 数据校验:周期性对源端与目标端的数据进行抽样对比,发现不一致时触发修复流程。
  • 断点续传:记录每个阶段的处理进度(Offset),在组件重启后从断点继续。
  • 回滚指令:当检测到严重数据错误或业务方发起回滚请求时,停止写入并启动回滚流程。
回滚策略:推荐使用增量回滚而非全量回滚。增量回滚只回滚从某个时间点开始的变更,保留已校验通过的历史数据,大幅缩短回滚窗口。

下图展示了监控与回滚领域内部的组件协作关系:

监控与回滚领域组件协作图 监控与回滚领域组件协作 延迟监控 Prometheus + Grafana 数据校验 校验和 / 行数对比 断点续传 Offset 持久化 回滚引擎 指令下发 事件总线 / 消息队列 Kafka / Pulsar 回滚指令传播路径 说明

4.7 接口契约定义

流水线各阶段之间通过明确的接口契约进行解耦。以下是核心接口定义:

// 阶段间事件接口(基于 Apache Avro / Protobuf)
syntax = "proto3";

message ChangeEvent {
  string source_id = 1;          // 源数据库实例标识
  string table_name = 2;         // 表名
  int64  timestamp = 3;          // 事件产生时间(毫秒)
  string op_type = 4;            // c / u / d / r
  bytes  before = 5;             // 变更前数据(JSON 或 Avro 编码)
  bytes  after = 6;              // 变更后数据
  int64  offset = 7;             // 日志偏移量
  map<string, string> headers = 8; // 扩展头(如事务 ID、路由标签)
}

// 监控上报接口
message MonitorMetric {
  string pipeline_id = 1;
  string stage_name = 2;         // source / capture / transform / target
  int64  lag_ms = 3;             // 延迟毫秒数
  int64  processed_count = 4;    // 已处理事件数
  int64  error_count = 5;        // 错误事件数
  double throughput = 6;         // 当前吞吐量(events/s)
}

// 回滚指令接口
message RollbackCommand {
  string pipeline_id = 1;
  int64  rollback_to_offset = 2; // 回滚到指定偏移量
  string reason = 3;             // 回滚原因
  bool   dry_run = 4;            // 是否为预演模式
}
契约驱动开发(CDD):所有阶段实现都基于上述接口进行单元测试与集成测试。接口版本化(如 v1、v2)确保流水线在升级过程中保持向后兼容。

4.8 架构决策记录(ADR)

下表总结了本章架构设计中的关键决策及其依据:

决策编号 决策内容 备选方案 选择理由
ADR-004-01 CDC 使用独立进程而非嵌入源库 嵌入式 CDC(如 MySQL UDF) 独立进程不侵入源库,便于独立扩缩容与故障隔离
ADR-004-02 转换引擎采用无状态设计 有状态转换(如状态机) 无状态便于水平扩展,状态统一外置到 Redis
ADR-004-03 监控与回滚使用独立事件总线 直接 API 调用 事件总线解耦监控与业务逻辑,支持异步处理与多消费者
ADR-004-04 回滚采用增量回滚策略 全量重导 增量回滚时间可控(分钟级 vs 小时级),对业务影响最小