一、背景:为什么需要 CDC?
1.1 传统数据集成的痛点
在数据仓库和数据湖建设中,将业务数据库的数据同步到分析系统是最基础也最关键的环节。传统方案主要有两种:
|
方案 |
原理 |
问题 |
|
全量定时抽取(如 DataX/Sqoop) |
定期 SELECT 全表数据 |
延迟高(通常 T+1)、资源浪费大、对源库压力大 |
|
基于时间戳增量抽取 |
按 update_time 字段拉取增量 |
无法捕获删除操作、依赖业务表设计、时间窗口容易遗漏数据 |
这两种方式的核心缺陷在于无法实时感知数据变更,且对业务系统存在侵入性。
1.2 CDC 技术的演进
CDC(Change Data Capture,变更数据捕获)技术通过监听数据库日志(如 MySQL Binlog、PostgreSQL WAL)来捕获数据变更,天然具备:
- 实时性:变更即时捕获,端到端延迟可达亚秒级
- 完整性:INSERT / UPDATE / DELETE 全部捕获,不遗漏
- 低侵入:读取日志而非查询表,对源库几乎无影响
CDC 领域的关键里程碑:
|
时间 |
事件 |
意义 |
|
2011 |
LinkedIn 开源 Databus |
早期 CDC 方案,绑定特定数据库 |
|
2017 |
Debezium 1.0 发布 |
基于 Kafka Connect 的通用 CDC 框架 |
|
2020 |
Flink CDC 1.0 发布 |
将 CDC 与流计算深度融合 |
|
2021 |
Flink CDC 2.0 发布 |
增量快照算法,无锁并发读取 |
|
2023.12 |
Flink CDC 3.0 发布 |
YAML Pipeline,端到端数据集成平台 |
|
2024.05 |
Flink CDC 3.1(加入 Apache Flink 子项目) |
transform + route 能力 |
|
2025.05 |
Flink CDC 3.4 发布 |
新增 Iceberg sink、Batch 执行模式 |
1.3 Flink CDC 的定位
Flink CDC 是 Apache Flink 的子项目,定位为「分布式实时数据集成工具」,它可以把数据库表的全量数据和增量变更数据接入 Flink,使数据库表在 Flink 中表现为一张持续变化的动态表。与传统 Debezium + Kafka 方案相比,它最大的差异是去除了中间件依赖,将 Source → Transform → Sink 整合为单一 Flink 作业,降低了架构复杂度和运维成本。
从使用视角看,Flink CDC 通常有两类能力:
- Flink SQL / Table API Source Connector
- 在 Flink SQL 中通过 CREATE TABLE … WITH ('connector' = 'mysql-cdc') 等方式定义 CDC 源表;
- 适合实时 ETL、实时宽表、实时数仓建模。
- Flink CDC Pipeline / Data Integration 能力
- 通过 YAML 等声明式方式定义 source、sink、route、transform 等;
- 更偏向端到端数据同步与整库同步。
二、架构设计与核心原理
2.1 整体架构(Flink CDC 3.x)
Flink CDC 3.x 采用四层架构设计:

2.2 数据模型抽象
Flink CDC 将外部系统的存储对象统一抽象为「表(Table)」,每个表由 Table ID(namespace + schemaName + tableName 三元组)唯一标识。
内部数据流基于 Event 接口传输,分为两类:
- DataChangeEvent:数据变更事件,包含 before(变更前)和 after(变更后)字段值,类型有 INSERT / UPDATE / DELETE / REPLACE
- SchemaChangeEvent:结构变更事件,包含 AddColumn、DropColumn、AlterColumnType、RenameColumn、CreateTable、DropTable、TruncateTable 等
2.3 核心算法:增量快照(Incremental Snapshot)
增量快照算法是 Flink CDC 的核心创新(借鉴 Netflix DBLog 论文),解决了传统 CDC 全量阶段需要锁表的致命问题。

关键优势:
- 无锁设计:全程不需要 FLUSH TABLES WITH READ LOCK,对线上业务零影响
- 并发读取:多个 SourceReader 并行处理不同 Chunk,水平扩展能力强
- 断点续传:基于 Flink Checkpoint 机制,支持 Chunk 粒度的故障恢复
- Exactly-Once 语义:结合 Flink 的两阶段提交,保证端到端精确一致
2.4 Schema Evolution 机制
Flink CDC 3.x 支持上游 DDL 变更的实时同步,通过 SchemaOperator 和 SchemaRegistry 协调实现(schema.change.behavior):
|
行为模式 |
配置值 |
说明 |
|
异常中断 |
exception |
遇到 DDL 变更直接抛出异常 |
|
严格应用 |
evolve |
强制将 DDL 变更同步到下游,失败则触发 Failover |
|
尝试应用 |
try_evolve |
尝试同步 DDL,失败则忽略继续 |
|
宽松模式 |
lenient(默认) |
仅应用下游兼容的 DDL 变更 |
|
完全忽略 |
ignore |
忽略所有 DDL 变更 |
三、优缺点对比分析
3.1 核心优势
|
优势 |
说明 |
|
架构简洁 |
单一 Flink 作业,无需 Kafka/Kafka Connect 等中间件 |
|
无锁全量读取 |
增量快照算法,全量阶段不锁表、不影响在线业务 |
|
并发水平扩展 |
全量阶段多并发读取,增量阶段可按表并行 |
|
端到端 Exactly-Once |
结合 Flink Checkpoint + 两阶段提交保障一致性 |
|
Schema 自动演进 |
上游 DDL 变更可自动同步到下游 |
|
声明式 YAML |
零 Java 代码,YAML 定义全链路同步 |
|
整库同步 |
一个作业可同步整个数据库所有表 |
|
低延迟 |
省去 Kafka 中间层,亚秒级端到端延迟 |
3.2 局限与不足
|
局限 |
说明 |
应对建议 |
|
Sink 单一消费 |
一条 Pipeline 只能写入一个 Sink,不支持广播到多消费者 |
需要多消费者时仍需引入 Kafka |
|
生态宽度有限 |
Sink 连接器不如 Kafka 生态丰富 |
3.x 版本在持续扩展(已支持 Doris/StarRocks/Paimon/Iceberg/Fluss 等) |
|
大状态管理压力 |
整库同步时 State 可能很大,对 RocksDB 和 Checkpoint 存储要求高 |
合理设置并行度、使用增量 Checkpoint |
|
运维成熟度 |
相比 Debezium+Kafka 方案,社区运维经验积累相对较少 |
建立完善的监控体系 |
|
Schema 变更风险 |
复杂 DDL(如列类型收窄)可能导致下游兼容问题 |
使用 try_evolve 或 lenient 模式 |
四、适用场景
4.1 推荐使用 Flink CDC 的场景
- 实时数据入仓/入湖:MySQL/PostgreSQL → Doris/StarRocks/Paimon/Iceberg,追求低延迟和简单架构
- 整库同步:将业务库全量表一次性同步到分析系统,减少连接占用
- 分库分表合并:通过 route 规则将上游分片表路由合并到下游单表
- 实时 ETL 流水线:结合 transform 做列投影、过滤、计算列等轻量 ETL
- 实时物化视图:数据库变更驱动的实时聚合/指标计算
- 数据库迁移:利用全量+增量无缝切换实现在线迁移
4.2 不推荐使用 Flink CDC 的场景
- 需要多下游消费同一数据源:此时 Kafka 作为解耦层更合适
- 需要数据回放能力:Kafka 天然支持按 offset 回放
- 源端非关系型数据库且无成熟连接器:需确认连接器可用性
- 超大规模(数千张表)且表间有复杂依赖:单一 Pipeline 的状态管理可能成为瓶颈
五、配置详解(Flink CDC 3.x YAML Pipeline)
5.1 配置结构总览
一个完整的 Flink CDC YAML Pipeline 由以下部分组成:
source: # [必填] 数据源配置
type: mysql
…
sink: # [必填] 数据目标配置
type: doris
…
route: # [可选] 表路由规则
– source-table: …
sink-table: …
transform: # [可选] 数据转换规则
– source-table: …
projection: …
filter: …
pipeline: # [必填] 流水线全局配置
name: …
parallelism: …
5.2 Source 配置(以 MySQL 为例)
核心连接参数
|
参数 |
必填 |
默认值 |
说明 |
|
type |
是 |
– |
连接器类型,如 mysql |
|
hostname |
是 |
– |
数据库主机地址 |
|
port |
否 |
3306 |
数据库端口 |
|
username |
是 |
– |
用户名 |
|
password |
是 |
– |
密码 |
|
tables |
是 |
– |
监控的表,支持正则(如 db.\\.*) |
|
tables.exclude |
否 |
– |
排除的表 |
|
server-id |
否 |
– |
MySQL server-id,集群中需唯一(如 5400-5404) |
快照与增量参数
|
参数 |
默认值 |
说明 |
|
scan.startup.mode |
initial |
启动模式:initial(全量+增量)、latest-offset(仅增量)、snapshot(仅全量)等 |
|
scan.incremental.snapshot.chunk.size |
8096 |
Chunk 行数,影响全量阶段并发粒度 |
|
scan.snapshot.fetch.size |
1024 |
每次 fetch 的最大行数 |
|
scan.incremental.close-idle-reader.enabled |
false |
快照完成后关闭空闲 Reader,节省资源 |
|
connection.pool.size |
20 |
连接池大小 |
|
server-time-zone |
– |
数据库时区(避免 8 小时偏移问题) |
启动模式详解
|
模式 |
行为 |
|
initial(默认) |
先执行全量快照,再无缝切换到增量 Binlog |
|
latest-offset |
跳过全量,从最新 Binlog 位点开始(仅捕获启动后的变更) |
|
earliest-offset |
从最早可用 Binlog 位点开始 |
|
specific-offset |
从指定 Binlog 位点/GTID 开始 |
|
timestamp |
从指定时间戳位点开始 |
|
snapshot |
仅执行全量快照,完成后退出 |
5.3 Sink 配置(以 Doris 为例)
sink:
type: doris
fenodes: 127.0.0.1:8030
username: root
password: ""
table.create.properties.light_schema_change: true
table.create.properties.replication_num: 1
5.4 Route 配置(表路由)
route:
– source-table: app_db.orders # 精确匹配
sink-table: ods_db.ods_orders
– source-table: app_db.order_\\d+ # 正则匹配 – 分表合并
sink-table: ods_db.ods_orders_all
description: "分表合并"
5.5 Transform 配置(数据转换)
transform:
– source-table: app_db.users
projection: id, UPPER(name) AS name, age, created_at # 列投影 + 计算列
filter: age > 18 AND status = 'active' # 行过滤
description: "过滤未成年用户"
5.6 Pipeline 全局配置
|
参数 |
默认值 |
说明 |
|
name |
– |
作业名称 |
|
parallelism |
1 |
全局并行度 |
|
schema.change.behavior |
lenient |
DDL 变更处理策略 |
|
execution.runtime-mode |
STREAMING |
运行模式(STREAMING / BATCH) |
|
local-time-zone |
– |
时区设置 |
5.7 完整配置示例
source:
type: mysql
hostname: 192.168.1.100
port: 3306
username: cdc_user
password: ${CDC_PASSWORD}
tables: trade_db.\\.*
tables.exclude: trade_db.tmp_.*
server-id: 5400-5404
scan.startup.mode: initial
scan.incremental.snapshot.chunk.size: 16384
scan.snapshot.fetch.size: 2048
scan.incremental.close-idle-reader.enabled: true
connection.pool.size: 30
sink:
type: doris
fenodes: 10.0.0.1:8030
username: doris_admin
password: ${DORIS_PASSWORD}
table.create.properties.light_schema_change: true
table.create.properties.replication_num: 3
route:
– source-table: trade_db.orders
sink-table: ods.ods_orders
– source-table: trade_db.order_detail_\\d+
sink-table: ods.ods_order_detail_all
description: "订单明细分表合并"
transform:
– source-table: trade_db.users
projection: id, name, phone, city, created_at
filter: status != 'deleted'
description: "过滤已删除用户,裁剪敏感列"
pipeline:
name: Trade DB Full Sync to Doris
parallelism: 4
schema.change.behavior: try_evolve
local-time-zone: Asia/Shanghai
六、最佳实践
6.1 生产部署建议
资源规划:
- 并行度设置:建议按表数量和吞吐量需求设置,初始全量阶段可适当调高(如 4-8),增量阶段可降低
- 内存配置:TaskManager 建议 4-8GB,大表场景需关注 RocksDB State 大小
- Checkpoint 配置:间隔 1-3 分钟(金融场景 30s),使用增量 Checkpoint + 持久化存储(S3/HDFS)
server-id 配置:
# 使用范围语法,每个并发分配独立 ID
server-id: 5400-5408 # 如果 parallelism=4,至少需要 4 个 ID
⚠️ 注意:server-id 在 MySQL 集群中必须全局唯一,不能与主从复制的 slave ID 冲突。
时区一致性:
source:
type: mysql
server-time-zone: Asia/Shanghai # 必须与源库会话时区一致
pipeline:
local-time-zone: Asia/Shanghai
⚠️ 注意:时区不一致是生产中最常见的数据错误来源之一(典型表现为时间偏移 8 小时)。
6.2 性能调优手册
|
调优项 |
建议 |
原理 |
|
增大 chunk.size |
8192 → 16384 ~ 65536 |
减少 Chunk 数量,提升全量读取速度 |
|
增大 fetch.size |
1024 → 2048 ~ 4096 |
减少网络往返,提升单 Chunk 读取效率 |
|
开启 close-idle-reader |
true |
全量完成后释放空闲 Reader 资源 |
|
合理设置并行度 |
按表数量和下游承载力 |
避免过高导致 Source 连接过多或 Sink 压力过大 |
|
Sink 批写配置 |
增大 batch size / flush interval |
减少下游小写入,提升吞吐 |
|
列裁剪 |
Transform 中只投影必要列 |
减少网络传输和序列化开销 |
|
State Backend |
使用 RocksDB + 增量 Checkpoint |
适应大状态场景 |
6.3 监控关键指标
|
指标 |
关注点 |
告警阈值建议 |
|
端到端延迟(E2E Latency) |
P95/P99 |
> 5s 告警 |
|
Backpressure |
定位瓶颈在 Source/Transform/Sink |
isBackPressured 持续 true |
|
Checkpoint 成功率 |
失败影响恢复能力 |
连续 3 次失败告警 |
|
Binlog 位点差值(Record Lag) |
与源端最新位点的差值 |
持续增大告警 |
|
吞吐量 TPS |
异常下降 |
下降 > 30% 告警 |
|
Sink 写入错误率 |
唯一键冲突/超时等 |
> 0.1% 告警 |
6.4 常见故障排查
|
故障现象 |
原因 |
解决方案 |
|
server-id xxx is already in use |
ID 与其他 Slave 冲突 |
更换唯一的 server-id 范围 |
|
时间错位 8 小时 |
时区配置不一致 |
配置 server-time-zone |
|
全量阶段卡住 |
大表快照/锁等待/带宽不足 |
增大 chunk.size、检查网络 |
|
下游写入报错 |
鉴权/建表失败/唯一键冲突 |
检查 Sink 连接和表结构 |
|
Sink 反压严重 |
下游写入能力不足 |
增大 Sink 并发/批写参数 |
|
DDL 变更不兼容 |
列类型收窄/重命名 |
使用 try_evolve 或手动处理 |
七、总结与展望
Flink CDC 3.x 代表了实时数据集成领域的一个重要方向——声明式、端到端、去中间件化。它的核心价值在于:
- 通过增量快照算法实现了无锁、并发、可恢复的全增量一体化同步
- 通过 YAML Pipeline 实现了零代码的数据集成体验
- 通过 Schema Evolution 实现了上游 DDL 变更的自动传播
- 作为 Apache Flink 子项目,拥有强大的社区支撑和活跃的迭代节奏
对于技术栈以 Flink 为核心、目标是构建实时数仓/湖仓一体架构的团队,Flink CDC 是目前最值得优先评估的方案。






