Flink 2.3.0 从理论到实践 —— 第 14 章 Flink CDC 3.x 数据同步

课程定位:第五篇数据集成续。Kafka 入报文后,MySQL 维表如何同步入湖?本章讲解 CDC 原理(Binlog/Debezium)、Flink CDC 3.x Pipeline YAML 架构、MySQL CDC 全量+增量与 Schema 演进、Kafka/Paimon CDC、Transform 模块(投影/过滤/计算列/路由)、多 Sink 路由(Doris + Paimon)、断点续传与 Exactly-Once------这是维表入湖与整库同步的核心通道。

版本基线:Flink 2.3.0 + Flink CDC 3.6.x(适配 Flink 2.3)+ MySQL 8.0/8.4 + Paimon 1.4.x + Doris 4.1

配套教程:Apache Flink CDC 3.5.0 从理论到实践(基础理论)


章节导读

  • [14.1 CDC 原理:Binlog 与 Debezium](#14.1 CDC 原理:Binlog 与 Debezium)
  • [14.2 Flink CDC 3.x 架构(Pipeline / YAML)](#14.2 Flink CDC 3.x 架构(Pipeline / YAML))
  • [14.3 MySQL CDC:全量 + 增量、Schema 演进](#14.3 MySQL CDC:全量 + 增量、Schema 演进)
  • [14.4 Kafka CDC / Paimon CDC](#14.4 Kafka CDC / Paimon CDC)
  • [14.5 Transform 模块:投影、过滤、计算列、路由](#14.5 Transform 模块:投影、过滤、计算列、路由)
  • [14.6 多 Sink 路由:Doris + Paimon](#14.6 多 Sink 路由:Doris + Paimon)
  • [14.7 断点续传与 Exactly-Once](#14.7 断点续传与 Exactly-Once)
  • [14.8 本章小结与下章预告](#14.8 本章小结与下章预告)

14.1 CDC 原理:Binlog 与 Debezium

14.1.1 什么是 CDC

CDC(Change Data Capture,变更数据捕获)是捕获数据库增量变更的技术:源库每条 INSERT/UPDATE/DELETE 实时捕获,下游同步消费。

复制代码
┌──────────────────────────────────────────────────────────────┐
│              CDC 同步 vs 批量同步                            │
└──────────────────────────────────────────────────────────────┘

  批量同步(定时全量):              CDC 同步(实时增量):
  ┌────────┐  每天 00:00          ┌────────┐  实时
  │ MySQL  │ ──全量拉取──►        │ MySQL  │ ──binlog──►
  └────────┘                      └────────┘
     │                                │
     ▼                                ▼
  滞后 1 天,带宽大               延迟秒级,增量小
维度 批量同步 CDC 同步
延迟 小时~天 秒级
带宽 全表扫描 增量传输
源库压力 全表锁 binlog 读
实时性 ❌ ✅

14.1.2 MySQL Binlog

MySQL Binlog(二进制日志)记录所有已提交的 DDL/DML,是 CDC 的数据源。

Binlog 格式 说明 CDC 支持
STATEMENT SQL 语句 ❌(不确定性)
ROW 行级变更(before/after) ★ CDC 必需
MIXED 混合 ⚠️(部分可读)
sql 复制代码
-- MySQL 开启 ROW 格式 binlog(CDC 前置)
SET GLOBAL binlog_format = 'ROW';
SET GLOBAL binlog_row_image = 'FULL';   -- 记录完整 before/after

项目硬约束 :MySQL CDC 要求 binlog_format=ROW + binlog_row_image=FULL。binlog_row_image=MINIMAL 只记变更列,before 不全,CDC 还原 UPDATE/DELETE 会丢字段。

14.1.3 Debezium

Debezium 是基于 Kafka Connect 的 CDC 框架,将 binlog 转为 Kafka 消息(debezium-json 格式)。Flink CDC 内部借鉴 Debezium 的 binlog 解析 ,但不依赖 Kafka Connect------直连 MySQL,无需中间 Kafka。

维度 Debezium(Kafka Connect) Flink CDC(直连)
架构 MySQL → Kafka → Flink MySQL → Flink
中间件 需 Kafka + Connect ❌ 无需
全量+增量 需额外工具 ✅ 内置全量+增量
部署 复杂 简单
一致性 需保障 ★ Flink EOS

选型 :已有 Kafka Connect 生态 → Debezium + debezium-json 格式(第 13 章);无 Kafka 中间件 → Flink CDC 直连。车联网项目用 Flink CDC 直连,维表直接入 Paimon。


14.2.1 3.x 架构演进

复制代码
┌──────────────────────────────────────────────────────────────┐
│              Flink CDC 架构演进                              │
└──────────────────────────────────────────────────────────────┘

  2.x(SourceFunction):           3.x(Pipeline YAML):
  ┌──────────┐                   ┌──────────┐
  │ MySQL    │ ──Source──►       │ source   │ (MySQL/Kafka/Paimon)
  │ Source   │   Flink SQL       │          │
  └──────────┘   单表            ├──────────┤
                 无路由           │ transform│ (投影/过滤/计算列/路由)
                                 │          │
                                 ├──────────┤
                                 │ sink     │ (Doris/Paimon/Kafka)
                                 │ 多 sink  │
                                 └──────────┘
                                 整库同步 + 多 sink 路由
版本 特性
2.x 单表 Source(SourceFunction),Flink SQL 消费
3.x Pipeline YAML:整库同步、Transform 模块、多 Sink 路由、Schema 演进

14.2.2 Pipeline YAML 四段式

yaml 复制代码
source:           # ① 数据源
  type: mysql
  ...

pipeline:         # ② 管道配置
  name: ...
  parallelism: 2
  schema.change.behavior: evolve

transform:        # ③ 变换(可选)
  - source-table: ...
    projection: ...
    filter: ...

sink:             # ④ 目的地
  type: paimon / doris / kafka
  ...

route:            # ⑤ 路由(可选,source → sink 映射)
  - source-table: ...
    sink-table: ...
段 作用 必填
source 数据源类型与连接 ✅
pipeline 管道名、并行度、Schema 演进 ✅
transform 投影/过滤/计算列 可选
sink 目的地类型与连接 ✅
route source 表 → sink 表映射 可选

14.3 MySQL CDC:全量 + 增量、Schema 演进

14.3.1 全量 + 增量无缝切换

Flink CDC MySQL Source 支持全量+增量一体化:先全量快照,再切 binlog 增量,无锁。

复制代码
┌──────────────────────────────────────────────────────────────┐
│              MySQL CDC 全量+增量切换                        │
└──────────────────────────────────────────────────────────────┘

  ① 全量阶段(快照)         ② 切换点           ③ 增量阶段(binlog)
  SELECT * FROM table       记录 binlog 位点   消费 binlog
  分片并发读              ──────────────►     从位点续读
  无锁(基于 MVCC)           (一致性切点)        不重不丢
阶段 机制 锁
全量快照 分片 SELECT,基于 MVCC 快照 无锁
切换点 记录 binlog 位点 + 全量完成标记 短暂(位点记录)
增量消费 从位点读 binlog 无锁

2.x 的痛点 :旧 CDC 全量阶段用 FLUSH TABLES WITH READ LOCK(全局读锁),影响在线业务。3.x 基于 MVCC 快照无锁全量,生产可用。

14.3.2 项目实战:MySQL 维表整库同步入 Paimon

车联网项目 MySQL 维表(车型/车系/车辆信息)用 Flink CDC YAML pipeline 同步入湖:

yaml 复制代码
source:
  type: mysql
  hostname: xxx.xxx.xxx.xxx
  port: 3306
  username: xxx
  password: xxx
  tables: iov_veh.t_cn_car_info,iov_veh.t_cn_car_series, iov_veh.t_cn_car_type
  server-id: 5410-5418          # ★ server-id 区间,多并行度防冲突
  server-time-zone: Asia/Shanghai

sink:
  type: paimon
  catalog.properties.metastore: hive
  catalog.properties.uri: thrift://hm-1:9083,thrift://hm-2:9083
  catalog.properties.warehouse: hdfs:///warehouse/tablespace/managed/hive

pipeline:
  name: vehicle_dim_to_tsp_ods_paimon
  parallelism: 2
  schema.change.behavior: evolve    # ★ MySQL DDL 变更自动演进到 Paimon

route:
  - source-table: iov_veh.t_cn_car_info
    sink-table: tsp_ods.ods_iov_veh_t_cn_car_info
  - source-table: iov_veh.t_cn_car_series
    sink-table: tsp_ods.ods_iov_veh_t_cn_car_series
  - source-table: iov_veh.t_cn_car_type
    sink-table: tsp_ods.ods_iov_veh_t_cn_car_type
要点 说明
schema.change.behavior: evolve ★ 源端加列自动同步,维表结构变更零人工
server-id 配区间 ★ 增量读取按并行度拆分 binlog 位点,配单个 id 多并行会冲突
维表入湖后用途 实时作业 FOR SYSTEM_TIME AS OF 做 LOOKUP JOIN;离线批作业直接批读------一份维表两链路共享

项目硬约束① :server-id 必须配区间(如 5410-5418),不要配单个------多并行度时各 SubTask 抢同一个 server-id 会冲突,binlog 读取失败。

项目硬约束② :维表入湖后,实时作业用 FOR SYSTEM_TIME AS OF 做 LOOKUP JOIN (见第 11 章),离线批作业直接批读------一份维表两链路共享,不需要单独维护实时维表。

14.3.3 Schema 演进

schema.change.behavior 控制 MySQL DDL 变更如何同步到下游:

取值 行为 适用
evolve ★ 自动加列、改类型 维表(推荐)
exception DDL 变更报错停止 严格管控
lenient 宽松(忽略不兼容) 容错
ignore 忽略 DDL 仅同步 DML

项目实践 :维表用 evolve------MySQL 加列自动同步到 Paimon,维表结构变更零人工。报文事实表 ODS 不用 CDC(Kafka 入湖),不涉及 Schema 演进。

14.3.4 提交方式

bash 复制代码
# 提交 YAML pipeline
flink-cdc.sh mysql-to-paimon.yaml \
  --flink-home /opt/flink \
  --jar flink-cdc-dist.jar

# 或用 sql-job 提交
flink run -c org.apache.flink.cdc.cli.CliFrontend \
  flink-cdc-dist.jar \
  mysql-to-paimon.yaml

项目硬约束(jar 加载) :CDC jar 与连接器 jar 同样遵循"jar 加载铁律"------只放一份到 ${FLINK_HOME}/lib,不要 -j 。-j 双 classloader 加载报 SPI not a subtype。判据:CDC jar 1 个 + Paimon jar 1 个 + 连接器版本唯一。


14.4 Kafka CDC / Paimon CDC

14.4.1 Kafka CDC Source

Flink CDC 3.x 支持以 Kafka 为 CDC Source,消费 Canal/Debezium/Maxwell 格式消息:

yaml 复制代码
source:
  type: kafka
  topic: cnx_vehicle_dim_cdc
  properties.bootstrap.servers: kafka-1:9092
  properties.group.id: ${group.id}
  scan.startup.mode: group-offsets
  value.format: debezium-json    # ★ CDC 格式
  key.format: json
Source 用途 中间件
MySQL CDC 直连 MySQL 无
Kafka CDC 消费已有 CDC 消息 需 Kafka + Canal/Debezium

选型:已有 Canal/Debezium 写 Kafka 的存量系统 → Kafka CDC Source;新建链路 → MySQL CDC 直连,更简单。

14.4.2 Paimon CDC Source

Paimon 表本身可作为 CDC Source(流读 changelog):

yaml 复制代码
source:
  type: paimon
  catalog.properties.metastore: hive
  catalog.properties.uri: thrift://hm-1:9083
  catalog.properties.warehouse: hdfs:///...
  tables: tsp_ods.ods_iov_veh_t_cn_car_info
  scan.mode: latest              # 流读模式

sink:
  type: doris
  ...
场景 用法
Paimon 维表 → Doris Paimon CDC Source + Doris Sink
Paimon 中间结果 → 下游表 Paimon CDC Source + Paimon Sink

项目硬约束 :Paimon CDC Source 流读必配 scan.mode=latest(非默认 latest-full),否则全量回放 OOM(见第 11 章)。


14.5 Transform 模块:投影、过滤、计算列、路由

14.5.1 Transform 四能力

yaml 复制代码
transform:
  - source-table: iov_veh.t_cn_car_info
    sink-table: tsp_ods.ods_car_info_clean
    projection: vin, car_series, car_type, UPDATE_TIME AS update_time
    filter: STATUS = 1 AND vin IS NOT NULL
  - source-table: iov_veh.t_cn_car_type
    sink-table: tsp_ods.ods_car_type_full
    projection: id, type_name, CREATE_TIME AS create_time
能力 语法 作用
投影 projection: col1, col2 选列
计算列 col_expr AS alias 派生列
过滤 filter: condition 行筛选
路由 route 段 表映射

14.5.2 实战:维表清洗

yaml 复制代码
transform:
  - source-table: iov_veh.t_cn_car_info
    sink-table: tsp_ods.ods_car_info_clean
    # 投影:选列 + 计算列(脱敏 + 重命名)
    projection: >
      VinMask(vin) AS masked_vin,
      car_series,
      car_type,
      CASE WHEN status=1 THEN 'ACTIVE' ELSE 'INACTIVE' END AS car_status,
      UPDATE_TIME AS update_time
    # 过滤:只同步有效车辆
    filter: vin IS NOT NULL AND LENGTH(vin) = 17

UDF 在 Transform 中 :Transform 的 projection / filter 可用已注册的 UDF(如 VinMask)。UDF jar 放 ${FLINK_HOME}/lib。

14.5.3 路由:多表分流

yaml 复制代码
route:
  # 车辆信息 → 维表
  - source-table: iov_veh.t_cn_car_info
    sink-table: tsp_ods.ods_car_info
  # 车辆类型 → 维表 + Doris 镜像(一路两写)
  - source-table: iov_veh.t_cn_car_type
    sink-table: tsp_ods.ods_car_type, doris_dim.dim_car_type

一路两写:route 可把一张源表路由到多个 sink 表,实现"Paimon 入湖 + Doris 镜像"同步------不需要两条作业。


14.6 多 Sink 路由:Doris + Paimon

14.6.1 多 Sink 配置

yaml 复制代码
sink:
  - type: paimon
    name: paimon-sink
    catalog.properties.metastore: hive
    catalog.properties.uri: thrift://hm-1:9083
    catalog.properties.warehouse: hdfs:///...
  - type: doris
    name: doris-sink
    fenodes: doris-fe-1:28030
    username: ${doris.user}
    password: ${doris.pwd}
    sink.enable-2pc: true
    sink.label-prefix: cdc-dim-doris

route:
  - source-table: iov_veh.t_cn_car_info
    sink-table: paimon-sink.tsp_ods.ods_car_info
  - source-table: iov_veh.t_cn_car_type
    sink-table: doris-sink.doris_dim.dim_car_type
Sink 特性 适用
Paimon 湖存储、批流共享 ★ 维表入湖
Doris 查询加速、Unique Key upsert BI 点查
Kafka append 流 中转/审计

项目实践:维表入 Paimon(两链路共享),明细表镜像到 Doris(BI 点查)。一份 CDC 作业,两份落地,零额外开发。

14.6.2 Doris Sink 的 2PC

Doris Sink 配 sink.enable-2pc=true 参与 Flink Checkpoint 两阶段提交------Checkpoint 成功才 commit,失败 abort,保证 Exactly-Once。sink.label-prefix 每作业唯一(见第 11 章)。


14.7 断点续传与 Exactly-Once

14.7.1 断点续传原理

复制代码
┌──────────────────────────────────────────────────────────────┐
│              CDC 断点续传                                   │
└──────────────────────────────────────────────────────────────┘

  全量快照 ──► binlog 位点 P1 ──► Checkpoint(记 P1) ──► 增量消费
                                    │
                          作业故障 │
                                    ▼
                          从 P1 恢复 ──► 续读 binlog(P1 之后)
                          (不重全量,不丢不重)
机制 说明
全量阶段位点 快照分片 + binlog 位点记入 Checkpoint
增量阶段位点 binlog 文件名 + position 记入 Checkpoint
故障恢复 从最近 Checkpoint 的位点续读,不重全量

14.7.2 Exactly-Once 保障

环节 EOS 保障
Source(MySQL CDC) binlog 位点记入 Checkpoint
Transform 无状态(投影/过滤)
Sink(Paimon) checkpoint commit(主键 upsert 幂等)
Sink(Doris) 2PC(enable-2pc=true)

端到端 EOS:Source 位点 + Sink 2PC/幂等,故障时从 Checkpoint 恢复,源重放 + 幂等去重,不重不丢。

14.7.3 改表无状态重启

项目硬约束 :表重建后作业 OutOfRangeException 崩溃循环------根因是有状态恢复,源表快照不连续。解法:停作业 → DDL → 无状态重启(不恢复 checkpoint,从最新位点起)。CDC 作业改表同样遵循此铁律。

操作 是否可状态恢复 风险
加列(evolve) ✅ 无
改类型 ⚠️ 可能不兼容
重建表(DROP+CREATE) ❌ 快照断裂,必须无状态重启
改 bucket 数 ❌ 同上

14.7.4 Savepoint 管理

bash 复制代码
# 停作业前做 savepoint(CDC 作业改表/升级必用)
flink stop --savepointPath hdfs:///savepoints/cdc-dim <jobId>

# 从 savepoint 重启(状态恢复)
flink run -s hdfs:///savepoints/cdc-dim/savepoint-xxx \
  -c org.apache.flink.cdc.cli.CliFrontend \
  flink-cdc-dist.jar mysql-to-paimon.yaml

Savepoint vs Checkpoint:Savepoint 是手动触发的全量状态快照,用于版本升级/计划停机;Checkpoint 是自动增量的容错快照。CDC 作业改表前先做 Savepoint,重启可恢复。


14.8 本章小结与下章预告

本章小结

复制代码
┌────────────────────────────────────────────────────────────────┐
│                     第 14 章 要点回顾                        │
└────────────────────────────────────────────────────────────────┘

  ✓ CDC 原理:
      Binlog(ROW 格式 + FULL image)是数据源
      Debezium 基于 Kafka Connect;Flink CDC 直连(无中间件)

  ✓ Flink CDC 3.x:
      Pipeline YAML 四段: source / pipeline / transform / sink
      整库同步 + 多 sink 路由 + Schema 演进

  ✓ MySQL CDC:
      全量+增量无锁切换(MVCC 快照)
      ★ server-id 配区间(多并行防冲突)
      ★ schema.change.behavior=evolve(加列自动同步)
      ★ jar 加载铁律: 只放 lib,绝不传 -j

  ✓ Kafka CDC / Paimon CDC:
      Kafka CDC: 消费 Canal/Debezium 格式
      Paimon CDC: 流读 changelog(scan.mode=latest)

  ✓ Transform:
      投影 / 计算列 / 过滤 / 路由
      一路两写: Paimon 入湖 + Doris 镜像

  ✓ 多 Sink 路由:
      Paimon(湖存储,两链路共享)
      Doris(BI 加速,2PC)
      一份 CDC,两份落地

  ✓ 断点续传 + EOS:
      binlog 位点记 Checkpoint
      Sink 2PC/幂等
      ★ 重建表必须无状态重启(快照断裂)
      Savepoint 用于版本升级/计划停机

下章预告

第 15 章 Paimon & Doris 湖仓写入:CDC 维表入湖后,如何写事实表与服务层。讲解 Paimon 写入(主键表/Append 表/Changelog Producer)、Paimon 读取(批读/流读/Lookup)、Paimon Catalog 注册、Doris Sink(Stream Load/2PC/部分列更新)、Doris Read(JDBC vs Doris Connector)、端到端 Exactly-Once 链路、湖仓一体 Flink+Paimon+Doris 协同。

官方参考资料

相关推荐
计算机编程指导师2 小时前
大数据毕业设计推荐:Hadoop+Django全球碳排放减排策略分析与可视化系统源码 毕业设计 选题推荐 毕设选题 数据分析 机器学习
大数据·hadoop·python·数据分析·spark·毕业设计·碳排放
计算机编程指导师2 小时前
Python大数据毕设怎么做?基于Hadoop+Spark的高频电力消耗数据可视化与分析系统源码 毕业设计 选题推荐 毕设选题 数据分析 机器学习
大数据·hadoop·python·spark·毕业设计·课程设计·电力
计算机编程指导师3 小时前
【计算机毕设】基于Hadoop+Spark的美国互联网银行贷款数据可视化分析系统源码 毕业设计 选题推荐 毕设选题 数据分析 机器学习
大数据·hadoop·python·数据分析·spark·毕业设计·贷款
data analyse 4564 小时前
服务端访问日志聚合 PV 与 UV 怎么实现?日志采集与口径设计
大数据·前端·数据分析
ZZ202601154 小时前
维普露禾平台免费开放,聊聊教育垂直大模型的RAG实现思路
大数据·人工智能·系统架构·知识图谱
小猴子爱上树4 小时前
跨境电商AI图片翻译工具:批量图片翻译、视频字幕翻译与智能抠图一站式解决
大数据·人工智能·python·音视频
七十二时9564 小时前
2026 企业级 AI 办公平台选型指南:如何判断哪些 AI 满足企业办公需求
大数据·人工智能
康实训4 小时前
CGA老年综合评估是什么?评估体系、核心维度与行业应用标准解析
大数据·人工智能·实训室·实训室建设
SelectDB5 小时前
Doris VARIANT 速查:类型映射、建表写法、索引配置与常见注意点
大数据·数据库·数据分析