3. 主流CDC工具概览

选型CDC工具时,最容易犯的错误是只看“能不能采集MySQL”,而忽略采集之后数据往哪里去、以什么格式去、由谁负责容错。Debezium、Canal、Flink CDC、Maxwell这四款工具都能从MySQL binlog读取变更,但它们在架构定位、部署形态、下游生态和运维责任上差异明显。理解这些差异,比记住功能列表更重要。

四款工具的定位差异

Debezium是Kafka Connect生态中的一组Source Connector,本身不独立运行,而是作为Kafka Connect插件部署。它把MySQL、PostgreSQL、MongoDB、Oracle等数据库的变更事件写入Kafka Topic,事件结构包含before、after、source、op等字段,天然适合“变更即消息”的架构。Debezium依赖Kafka Connect的分布式模式和Offset存储,容错、扩缩容、重启恢复都由Connect框架承担。它的优势是数据库种类多、事件格式规范、与Kafka生态无缝;代价是必须引入Kafka和Connect集群,链路较长。

Canal是阿里开源的独立CDC服务,模拟MySQL Slave协议向主库或从库发送dump请求,解析binlog后推送到Kafka、RocketMQ或直接由客户端拉取。Canal Server独立部署,自带Instance管理,一个Instance对应一个数据库实例的采集任务。它的优势是轻量、部署简单、对MySQL协议理解深入;局限是主要面向MySQL,下游生态需要自行对接,Exactly-Once语义依赖下游消费端实现。

Flink CDC把CDC采集能力内置到Flink Source中,通过增量快照算法实现全量+增量一体化读取。它不依赖Kafka Connect,也不要求先落Kafka,可以直接在Flink作业中完成采集、转换、写入下游。Flink CDC支持MySQL、PostgreSQL、Oracle、MongoDB等,配合Flink的Checkpoint机制提供Exactly-Once。它的优势是链路短、流批一体、状态管理成熟;代价是必须运行Flink集群,作业开发需要Flink SQL或DataStream API能力。

Maxwell是轻量级MySQL binlog订阅工具,输出JSON格式变更事件到Kafka、Kinesis、RabbitMQ或stdout。它由Java编写,单进程运行,配置简单,适合快速搭建“MySQL到Kafka”的同步链路。Maxwell不提供分布式协调,高可用需要借助外部工具或自行实现,功能边界相对窄,但胜在简单直接。

四款CDC工具的数据流向与依赖边界 MySQL binlog (ROW) Debezium Kafka Connect Source Kafka Topic / Connect Canal Server Instance / dump协议 Kafka / MQ 或客户端拉取 Flink CDC Source 增量快照 + Checkpoint Flink 作业 转换 / 写入下游 Maxwell 单进程 JSON 输出 Kafka / stdout 轻量下游 Debezium • 依赖 Kafka Connect 集群 • 多数据库、事件格式规范 • 适合变更入湖/入仓、事件驱动 Canal • 独立 Server,Instance 管理 • 主要面向 MySQL,部署轻量 • 适合已有 MQ 体系的同步链路 Flink CDC • 全量+增量一体化,流批一体 • 依赖 Flink 集群与 Checkpoint • 适合实时数仓、ETL 一体化 Maxwell • 单进程、JSON 输出、配置简单 • 高可用需外部保障,功能边界窄

功能边界的关键判断点

第一,是否要求先落Kafka。Debezium和Maxwell默认以Kafka为主要下游,Canal可以推Kafka也可以由客户端直接拉取,Flink CDC则完全不要求Kafka。如果团队已有Kafka且希望变更事件被多个消费者复用,Debezium和Canal更自然;如果希望采集后直接在流作业中完成清洗和写入,Flink CDC链路最短。

第二,全量+增量的处理方式。Debezium通过initial snapshot模式先做全量快照再切增量,快照期间需要锁表或使用一致性快照;Canal本身不负责全量,通常需要业务侧先做一次全量导出再启动增量;Flink CDC的增量快照算法支持无锁、并行、可断点续传的全量读取,这是它相对前两者的明显优势;Maxwell同样只做增量,全量需要另行处理。

第三,Exactly-Once的保障位置。Debezium依赖Kafka Connect的Offset提交和Kafka事务;Flink CDC依赖Flink Checkpoint和两阶段提交Sink;Canal和Maxwell本身不提供端到端Exactly-Once,需要下游消费端做幂等或去重。这一点直接决定故障恢复后是否会出现重复数据。

第四,运维复杂度。Maxwell最简单,单进程启动即可;Canal需要维护Server和Instance;Debezium需要维护Kafka Connect集群和Kafka;Flink CDC需要维护Flink集群、Checkpoint存储和作业管理。选型时要评估团队已有的基础设施,而不是只看工具本身。

适用场景对照

场景 推荐工具 理由
MySQL变更写入Kafka,供多消费者使用 Debezium / Canal 事件格式规范,Kafka生态成熟
实时数仓,采集后直接做ETL Flink CDC 全量+增量一体,流批统一
快速搭建MySQL到Kafka的轻量同步 Maxwell 单进程、配置少、上线快
多数据库异构采集 Debezium / Flink CDC 支持MySQL、PG、Oracle、MongoDB等
已有Flink集群,希望减少中间件 Flink CDC 无需额外维护Kafka Connect
仅MySQL,且希望独立部署、不绑Flink Canal 独立Server,Instance粒度管理

选型时的实操建议

如果团队已经在使用Kafka Connect,并且需要把多种数据库的变更统一写入Kafka,Debezium是首选。它的配置以JSON为主,一个MySQL Connector的典型配置包括:

{
  "name": "mysql-inventory-connector",
  "config": {
    "connector.class": "io.debezium.connector.mysql.MySqlConnector",
    "database.hostname": "mysql-primary",
    "database.port": "3306",
    "database.user": "debezium",
    "database.password": "******",
    "database.server.id": "184054",
    "database.server.name": "inventory",
    "database.include.list": "inventory",
    "table.include.list": "inventory.orders,inventory.customers",
    "database.history.kafka.bootstrap.servers": "kafka:9092",
    "database.history.kafka.topic": "schema-changes.inventory",
    "include.schema.changes": "true",
    "snapshot.mode": "initial"
  }
}

其中database.server.id必须全局唯一,不能与MySQL集群中已有Slave的server-id冲突;snapshot.mode设为initial表示先做全量快照再切增量,生产环境若表很大,需要评估快照对主库的压力,必要时改为schema_only或使用从库采集。

如果选择Flink CDC,核心是在Flink SQL中定义Source表并指定启动模式:

CREATE TABLE mysql_orders (
  id BIGINT,
  user_id BIGINT,
  amount DECIMAL(10,2),
  status STRING,
  update_time TIMESTAMP(3),
  PRIMARY KEY (id) NOT ENFORCED
) WITH (
  'connector' = 'mysql-cdc',
  'hostname' = 'mysql-primary',
  'port' = '3306',
  'username' = 'flinkcdc',
  'password' = '******',
  'database-name' = 'inventory',
  'table-name' = 'orders',
  'scan.startup.mode' = 'initial',
  'server-time-zone' = 'Asia/Shanghai'
);

scan.startup.mode可选initial、latest-offset、timestamp等,initial表示先全量再增量。Flink CDC的增量快照会把全量阶段拆成多个chunk并行读取,并通过Checkpoint记录进度,作业失败重启后可以从上次Checkpoint继续,不会重复全量。

选型不是非此即彼。实际生产中常见组合是:用Debezium或Canal把变更统一写入Kafka作为“变更总线”,再用Flink消费Kafka做实时计算;或者直接用Flink CDC采集MySQL写入Paimon/Iceberg/Hudi等湖表。关键是明确每一层的职责:谁负责采集、谁负责传输、谁负责计算、谁负责容错。
无论选择哪款工具,都必须确认MySQL的binlog_format=ROW、binlog_row_image=FULL,并确保采集账号具备REPLICATION SLAVE、REPLICATION CLIENT权限。Debezium和Flink CDC还需要访问information_schema读取表结构。这些前置条件不满足时,工具本身配置再正确也无法工作。

总结来看,Debezium强在生态和格式规范,Canal强在轻量和MySQL协议理解,Flink CDC强在全量增量一体和流批统一,Maxwell强在简单直接。选型的核心不是比较功能多少,而是看数据要从哪里来、到哪里去、由谁保证一致性、团队能维护什么基础设施。把这四个问题回答清楚,工具选择自然清晰。