Debezium、Kafka Connect 与 Flink CDC 实时同步生产实战

CDC(Change Data Capture)通过数据库日志捕获增删改,为缓存、搜索、数仓、事件驱动和跨库同步提供低侵入数据通道。生产 CDC 的难点不只是“能看到 Binlog”,还包括快照与增量衔接、位点、顺序、重复、Schema 变化、删除语义、重平衡、下游幂等、延迟和灾难恢复。本文覆盖 Debezium/Kafka Connect 与 Flink CDC 的主要运维方法。

CDC 事件可能包含个人信息、密码摘要、Token、订单和财务数据。上线前必须进行字段分级、最小权限、传输加密、Topic ACL、日志脱敏和保留策略设计。

一、先定义同步语义

需求必须回答:

  • 全量 + 增量,还是只从当前时刻捕获;
  • 是否允许秒级延迟;
  • 是否允许重复,如何去重;
  • 是否要求同一主键有序,是否要求跨表事务顺序;
  • 删除在下游表现为物理删除、软删除还是 Tombstone;
  • DDL 如何同步;
  • 下游不可用时可积压多久;
  • 源库日志能保留多久;
  • RPO、RTO 和重建成本。

“Exactly Once”不能只看一个组件的宣传。端到端恰好一次要求 Source 可回退到 Checkpoint,处理状态一致,Sink 能事务提交或幂等写入。

二、典型架构

MySQL/PostgreSQL/Oracle/SQL Server
        ↓ 数据库日志
Debezium Connector / Flink CDC Source
        ↓
Kafka Topic 或 Flink Pipeline
        ↓
Sink Connector / Flink Sink / 自定义消费者
        ↓
Elasticsearch、Doris、ClickHouse、数据湖、缓存

Debezium 常运行在 Kafka Connect 中,将变更事件写入 Kafka;Flink CDC 可直接构建端到端 Pipeline,也可将 CDC 事件写入 Kafka。两者可以组合,但应避免不必要的重复链路。

三、源数据库准备

MySQL

需配置 Row 格式 Binlog、唯一 Server ID、足够的日志保留和专用最小权限账号。大事务和无主键表会影响快照与下游处理。

SHOW VARIABLES LIKE 'log_bin';
SHOW VARIABLES LIKE 'binlog_format';
SHOW BINARY LOG STATUS;
SHOW BINARY LOGS;

PostgreSQL

逻辑复制依赖 wal_level=logical、Replication Slot 和 Publication。Slot 会阻止仍需的 WAL 被回收,Connector 长期停止可能撑满磁盘。

SELECT slot_name, active, restart_lsn, confirmed_flush_lsn
FROM pg_replication_slots;

Oracle 与 SQL Server

分别关注归档日志/补充日志/LogMiner 或 XStream,以及 SQL Server CDC/Agent、日志截断和权限。具体能力与授权边界必须按所用版本官方文档核对。

四、初始快照

初始快照读取历史数据,再切换到日志增量。风险包括:

  • 大表扫描影响 Buffer Cache 和磁盘;
  • 长事务或锁;
  • 快照持续时间超过日志保留;
  • 并发 DDL 导致 Schema 不一致;
  • 网络或 Connector 重启造成重扫;
  • 下游突然接收海量历史数据。

上线前压测快照吞吐,控制并发、Fetch Size 和分片范围,并为源端与下游预留容量。增量快照可按块补采部分表,但仍需验证所用连接器的边界。

五、事件结构与主键

Debezium 事件通常包含 before、after、op、source 和时间等信息。消费者不应只读取 after 而忽略操作类型。

{
  "before": {"id": 42, "status": "new"},
  "after":  {"id": 42, "status": "paid"},
  "op": "u",
  "source": {"table": "orders"}
}

无主键表难以稳定分区、更新和去重。生产应尽量补充主键;无法补充时,要明确使用哪些字段生成 Key,以及重复行和字段变更的处理方式。

六、Kafka Topic 设计

Topic 数量、分区数和保留时间需要同时满足吞吐、顺序和恢复窗口。

  • 同一 Key 放入同一分区,可保持分区内顺序;
  • 增加分区会改变 Key 到分区的映射,消费者状态需谨慎处理;
  • 日志保留必须覆盖最长下游中断和重放需求;
  • 压缩 Topic 可保留 Key 的最新值,但删除 Tombstone 和清理时机要理解;
  • Schema History Topic 与普通业务 Topic 权限、保留策略不同。

不要让 Schema History Topic 被短保留策略清空,否则 Connector 重建时可能无法正确解释历史 Schema。

七、Offset 与恢复

Offset 记录源日志位点。Kafka Connect 通常存于内部 Topic,Debezium Server/Engine 或其他部署方式有各自存储。备份范围必须包含:

  • Connector 配置;
  • Offset;
  • Schema History;
  • Topic 配置和 ACL;
  • 转换 SMT;
  • 密钥和证书。

错误重置 Offset 可能导致重复重放或跳过数据。任何位点调整都应先保存原值,并在隔离环境验证。

八、Kafka Connect 集群

Distributed 模式下多个 Worker 共享 Group。配置 Topic、Offset Topic 和 Status Topic 必须具有合适分区、复制因子和清理策略。

curl -s http://connect:8083/connectors
curl -s http://connect:8083/connectors/orders-cdc/status
curl -s http://connect:8083/connectors/orders-cdc/tasks/0/status

重平衡期间 Task 可能暂停。频繁扩缩容、Worker 网络抖动、插件版本不一致和长时间停止任务都会造成不稳定。

九、SMT 的使用边界

Single Message Transform 适合轻量字段路由、重命名、过滤和格式调整。不适合复杂 JOIN、大状态聚合或外部远程调用。

变换前考虑:

  • 是否丢失 before/source/op 导致无法追溯;
  • 删除事件是否被误过滤;
  • 字段改名与下游 Schema 兼容;
  • 敏感字段是在源侧、Connect 还是 Sink 脱敏;
  • 失败事件如何进入 DLQ。

Flink CDC 可用 YAML 描述 Source、Transform、Route、Sink 和 Pipeline。生产需配置 Checkpoint 到持久存储,并理解 Sink 的提交语义。

source:
  type: mysql
  hostname: db.example.internal
  port: 3306
  username: cdc_reader
  password: ${CDC_PASSWORD}
  tables: app_db.orders
  server-id: 5400-5404

sink:
  type: kafka
  properties.bootstrap.servers: kafka:9092
  topic: orders_cdc
  value.format: debezium-json

pipeline:
  name: orders-cdc
  parallelism: 2

示例中的密码应由密钥系统注入,不应提交到仓库。

十一、Checkpoint、Savepoint 与 Exactly Once

Checkpoint 是自动故障恢复状态,Savepoint 更偏向计划升级和迁移。生产 Checkpoint 应保存到持久分布式存储,监控耗时、失败和大小。

端到端 Exactly Once 还取决于:

  • Source 位点可回退;
  • Checkpoint 成功后状态一致;
  • Sink 支持事务或幂等;
  • 外部副作用纳入提交协议;
  • 故障恢复不会绕过旧事务清理。

即便系统语义是 Exactly Once,业务下游仍建议按主键与版本/位点实现幂等。

十二、Schema 演进

上游 DDL 可能新增、删除、重命名字段或改变类型。Flink CDC 支持多种 Schema Change 行为,例如严格失败、尝试演进、宽松或忽略。选择依据是下游能力和数据安全。

生产建议:

  • 新增 Nullable 字段优先;
  • 类型缩小、字段删除和改名需评审;
  • DDL 先在测试链路验证;
  • 记录上游/下游 Schema 版本;
  • 失败时暂停,不要静默丢字段;
  • 对不支持的 Sink 明确人工变更流程。

“自动同步 DDL”不是越自动越好,错误 Drop 可能传到分析库造成二次事故。

十三、删除与 Tombstone

数据库 Delete 事件可能产生带 before 的删除记录和后续 Tombstone。Sink 需要明确:

  • 删除目标行;
  • 标记 is_deleted;
  • 保留审计历史;
  • 忽略删除。

如果下游只做 Upsert 而忽略删除,数据会长期不一致。反之,错误匹配 Delete Key 可能删除不相关记录。

十四、延迟排查

把端到端延迟拆成:

源库日志产生
 → Connector 读取
 → Kafka 入队
 → 消费与处理
 → Sink 写入
 → 下游可查询

分别观察源端日志积压、Connector Source 时间戳、Kafka Consumer Lag、Flink Backpressure、Checkpoint、Sink 批量与错误。只看 Kafka Lag 为 0,不能证明下游已经可查询。

十五、背压与下游故障

下游慢时,Flink 会出现 Backpressure,Kafka Consumer Lag 增长,最终可能超过源日志或 Topic 保留窗口。处置:

  1. 保护数据,暂停无关作业;
  2. 确认下游容量、限流和错误;
  3. 调整批量、并发和重试;
  4. 防止无限重试阻塞所有分区;
  5. 对坏数据使用受控 DLQ;
  6. 恢复后限制追赶速率,避免冲垮下游。

十六、数据校验与对账

实时链路必须有持续对账。方法包括:

  • 分区/时间窗口行数;
  • 主键抽样;
  • 业务金额、状态等聚合;
  • 哈希分桶;
  • 延迟水位;
  • Delete/Update 数量;
  • Schema 一致性。

发现差异后,应能按表、主键区间或时间窗口重新同步,而不是只能全量重建。

十七、监控告警

监控 Connector/Task 状态、快照进度、源位点、日志保留窗口、Kafka Lag、DLQ、重试、Schema History、Flink Checkpoint、Backpressure、重启次数、Sink 错误、端到端延迟和对账差异。

告警要附带表、分区、位点、错误样本和恢复入口,但必须对敏感字段脱敏。

十八、上线清单

  • 源库日志、权限和保留窗口满足要求;
  • 表有稳定主键或明确替代策略;
  • 快照对源库和下游的压力已压测;
  • Offset、Schema History、Checkpoint 可恢复;
  • Delete、DDL、重复、乱序语义已测试;
  • 下游实现幂等或事务提交;
  • 具备 DLQ、重放和局部补数能力;
  • 端到端对账和延迟告警已启用;
  • 从故障位点恢复与全量重建均完成演练。

参考资料

  • Debezium Documentation:https://debezium.io/documentation/
  • Apache Kafka Connect:https://kafka.apache.org/documentation/#connect
  • Apache Flink CDC:https://nightlies.apache.org/flink/flink-cdc-docs-stable/
  • Flink Checkpointing:https://nightlies.apache.org/flink/flink-docs-stable/docs/dev/datastream/fault-tolerance/checkpointing/
Copyright © yan-jian.com 2023 - 2026 · Powered by GitBook更新时间: 2026-11-03 16:23:45

results matching ""

    No results matching ""