2. CDC 技术原理:从概念到主流工具实战

CDC,全称 Change Data Capture,中文叫变更数据捕获。说白了,就是实时监听数据库里的数据变化——谁新增了一条订单、谁修改了地址、谁删除了记录,CDC 都能第一时间告诉你。

我最早接触 CDC 是在 2017 年,那时候公司要做实时数仓,每天凌晨跑批处理,数据延迟至少 6 小时。业务方天天抱怨:「能不能实时看到今天的交易?」嗯,从那以后我就开始研究 CDC 了。

2.1 CDC 的核心概念

CDC 的本质,是把数据库的增量变更事件,转换成一条条可消费的消息。你想想看,传统 ETL 是「定时去查全表」,CDC 是「数据库主动告诉你变了什么」。这两种思路,效率天差地别。

CDC 的核心价值:

  • 低延迟:秒级甚至毫秒级捕获变更
  • 低侵入:不频繁查询源库,减少压力
  • 高保真:完整记录变更前后的数据

我在项目中遇到过一种情况:业务库白天高峰期 QPS 上万,如果用定时轮询的方式去拉增量数据,数据库 CPU 直接飙到 90%。换成 CDC 之后,CPU 降到 20% 以下。这就是 CDC 的魅力。

2.2 CDC 的三种实现方式

CDC 不是只有一种玩法。根据实现原理,主流有三种方式。我按推荐程度从高到低给你讲。

2.2.1 基于日志的 CDC(推荐)

这是目前最主流、最可靠的方式。数据库在写入数据时,会先写日志(比如 MySQL 的 binlog、PostgreSQL 的 WAL)。CDC 工具直接读取这些日志,解析出变更事件。

为什么推荐?因为它对源库几乎没有性能影响。日志本来就是数据库要写的,CDC 只是「顺路看一眼」。而且日志里记录了完整的事务信息,包括旧值和新值,数据一致性有保障。

我的经验: 基于日志的 CDC 是生产环境的首选。我曾经帮一家金融客户做实时风控,每天处理 2 亿条 binlog 事件,延迟稳定在 500 毫秒以内。只要日志不丢,数据就不会丢。

2.2.2 基于触发器的 CDC

这种方式是在源库的表上创建触发器(Trigger)。当有 INSERT、UPDATE、DELETE 操作时,触发器把变更记录写入一张专门的日志表。CDC 工具再去读这张日志表。

听起来挺合理对吧?但实际坑很多。触发器会增加数据库的事务开销,每写一次业务数据,就要额外写一次日志表。在高并发场景下,性能下降很明显。

避坑指南: 我曾经在一个电商项目里用过触发器方案,上线第一天就把订单库拖垮了。双十一大促期间,订单写入量暴增,触发器成了瓶颈。后来连夜改成基于日志的方案才稳住。所以,除非你的业务量极小(日均变更量 < 10 万),否则别用触发器。

2.2.3 基于时间戳的 CDC

这种方式最简单:在业务表里加一个 update_time 字段,然后定时查询 WHERE update_time > last_poll_time。很多早期的 ETL 工具就是这么干的。

但它有几个硬伤:

  • 无法捕获 DELETE 操作(除非用软删除)
  • 无法捕获 UPDATE 前的旧值
  • 频繁查询对数据库压力大
  • 时间精度不够时可能丢数据

我建议只在数据量小、对实时性要求不高的场景下使用。比如每天同步一次配置表,用时间戳就够了。

2.3 三种实现方式对比

对比维度 基于日志 基于触发器 基于时间戳
性能影响 极低 较高 中等
实时性 秒级 秒级 分钟级
捕获 DELETE 支持 支持 不支持
捕获旧值 支持 支持 不支持
侵入性 无 高 低
生产推荐度 ★★★★★ ★★☆☆☆ ★★★☆☆

2.4 主流 CDC 工具对比

选好了实现方式,接下来就是选工具。目前市面上最主流的三个 CDC 工具是:Debezium、Canal、Maxwell。它们都基于日志实现,但各有侧重。

2.4.1 Debezium

Debezium 是 Red Hat 开源的项目,基于 Kafka Connect 架构。它支持 MySQL、PostgreSQL、MongoDB、SQL Server 等多种数据库。我个人最喜欢它的地方是:

  • 原生集成 Kafka,一条龙服务
  • 支持 Schema 变更捕获(DDL)
  • 社区活跃,文档齐全
  • 支持增量快照,不停机同步历史数据

我在做实时数仓时,大部分场景都用 Debezium。尤其是需要同时监听多种数据库的场景,Debezium 的插件化架构非常方便。

2.4.2 Canal

Canal 是阿里巴巴开源的项目,专门针对 MySQL binlog。它的特点是:

  • 性能极高,阿里内部大规模验证过
  • 支持直接投递到 Kafka、RocketMQ、ES
  • 支持客户端订阅模式
  • 中文文档友好

如果你的源库是 MySQL,而且团队对 Java 技术栈比较熟悉,Canal 是个不错的选择。我记得有一次帮客户做 MySQL 到 ClickHouse 的实时同步,用 Canal 配合自研的消费端,延迟做到了 200 毫秒以内。

2.4.3 Maxwell

Maxwell 是 Zendesk 开源的项目,也是基于 MySQL binlog。它比 Canal 更轻量,部署非常简单:

  • 单 JAR 包运行,无需额外依赖
  • 输出格式为 JSON,易于消费
  • 支持 Kafka、Kinesis、RabbitMQ 等
  • 内置 Bootstrap 功能,支持全量+增量

Maxwell 适合中小规模场景。我曾在创业公司用过它,团队只有 3 个人,Maxwell 一个人就能搞定部署和维护。但要注意,Maxwell 不支持 DDL 变更捕获,也不支持多数据源同时监听。

2.5 工具选型对比表

对比维度 Debezium Canal Maxwell
支持数据库 MySQL、PG、MongoDB、SQL Server 等 仅 MySQL 仅 MySQL
架构 Kafka Connect 独立 Server + Client 单 JAR
DDL 捕获 支持 支持 不支持
输出格式 Avro / JSON / Protobuf JSON / 自定义 JSON
部署复杂度 中等 中等 低
社区活跃度 高 高 中
推荐场景 多数据源、大规模、复杂拓扑 纯 MySQL、高吞吐、Java 技术栈 小规模、快速部署、轻量需求

2.6 CDC 核心流程示意图

下面这张图展示了 CDC 从数据库到消息队列的完整链路。你可以看到,binlog 是源头,CDC 工具是桥梁,Kafka 是事件总线,下游的实时数仓、缓存、搜索引擎各取所需。

CDC 核心流程:从数据库到消息队列 源数据库 MySQL / PostgreSQL binlog / WAL 变更日志 CDC 工具 Debezium / Canal / Maxwell Kafka 事件总线 实时数仓 缓存 / Redis 搜索引擎 说明:CDC 工具订阅 binlog,解析为结构化事件,写入 Kafka,下游各系统按需消费

2.7 选型建议

说了这么多,到底怎么选?我根据实际项目经验,给你几个参考:

  • 如果你在搭建实时数仓,源库种类多 → 选 Debezium。它支持多种数据库,而且和 Kafka 生态无缝集成,适合长期建设。
  • 如果你只用 MySQL,追求极致性能 → 选 Canal。阿里内部验证过的方案,高并发场景下表现稳定。
  • 如果你团队小,想快速上线 → 选 Maxwell。一个 JAR 包搞定,配置简单,适合 MVP 阶段。

我的建议: 不管选哪个工具,生产环境一定要开启 Exactly-Once 语义。CDC 最怕丢数据或重复数据。Debezium 和 Canal 都支持通过 Kafka 的事务机制保证 Exactly-Once,Maxwell 则需要配合幂等消费。