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 是事件总线,下游的实时数仓、缓存、搜索引擎各取所需。
2.7 选型建议
说了这么多,到底怎么选?我根据实际项目经验,给你几个参考:
- 如果你在搭建实时数仓,源库种类多 → 选 Debezium。它支持多种数据库,而且和 Kafka 生态无缝集成,适合长期建设。
- 如果你只用 MySQL,追求极致性能 → 选 Canal。阿里内部验证过的方案,高并发场景下表现稳定。
- 如果你团队小,想快速上线 → 选 Maxwell。一个 JAR 包搞定,配置简单,适合 MVP 阶段。
我的建议: 不管选哪个工具,生产环境一定要开启 Exactly-Once 语义。CDC 最怕丢数据或重复数据。Debezium 和 Canal 都支持通过 Kafka 的事务机制保证 Exactly-Once,Maxwell 则需要配合幂等消费。