1、CDC技术概览:什么是CDC、CDC的典型应用场景、CDC主流工具对比
1.1 什么是CDC?说白了就是“监听数据库的变更”
CDC,全称Change Data Capture,翻译过来叫“变更数据捕获”。
我习惯这么跟团队里的新人解释:CDC就是给数据库装了一个“窃听器”。你往数据库里插一条数据、改一个字段、删一行记录,CDC都能实时感知到,并且把这些变更事件推送给下游系统。
你想想看,传统的数据同步怎么做?定时跑批,比如每天凌晨两点全量拉一次。这种方式有两个硬伤:一是数据延迟至少一天,二是每次跑批都要全表扫描,对源库压力很大。我早年在一个电商项目里就吃过这个亏——大促期间凌晨跑批直接把主库CPU打满,第二天被运维追着骂。
CDC就不一样了。它直接读取数据库的事务日志(比如MySQL的binlog、PostgreSQL的WAL),增量捕获变更,对源库几乎无侵入。延迟能做到秒级甚至毫秒级。
核心要点:CDC不是轮询查表,而是监听日志。这是它“轻量、实时、低侵入”的根本原因。
目前主流的CDC实现方式有两种:
- 基于日志的CDC:解析数据库的事务日志。性能最好,对源库影响最小。Debezium、Canal、Maxwell都是这条路。
- 基于查询的CDC:定期执行SQL查询,对比快照差异。实现简单,但延迟高、压力大。Flink CDC的“全量+增量”阶段会用到类似思路。
我个人更推荐基于日志的方案。除非你的数据库版本太老不支持日志解析,否则别走查询的老路。
1.2 CDC的典型应用场景
CDC能做的事情比你想象的多。我挑三个最常用的场景聊聊。
1.2.1 数据同步:从A库到B库的“高速公路”
这是CDC最基础的应用。把MySQL的数据实时同步到Elasticsearch、Redis、Kafka或者另一个数据库。
举个例子:你在MySQL里维护商品信息,搜索服务需要基于ES提供全文检索。传统做法是写个定时任务,每5分钟同步一次。但5分钟的延迟意味着用户改了商品标题后,搜索里还是旧数据。用CDC的话,商品表一有变更,ES索引立刻更新,体验完全不一样。
我在一个跨境电商项目里做过类似的同步链路:MySQL → Debezium → Kafka → 自研消费者 → ES。延迟稳定在500ms以内,线上跑了两年没出过大问题。
1.2.2 实时数仓:让OLAP也能“热乎”
传统数仓是T+1的,今天看昨天的数据。但业务决策越来越需要实时性——比如实时大屏、实时风控、实时推荐。
CDC可以把业务库的变更实时流入数仓(比如ClickHouse、Doris、Hudi)。这样分析师查到的就是“刚刚发生”的数据,而不是昨天的快照。
说白了,CDC是实时数仓的“水源”。没有CDC,实时数仓就是无米之炊。
1.2.3 缓存失效:告别“缓存与数据库不一致”
缓存失效是个经典问题。很多团队的做法是:更新数据库后,手动调用代码删除缓存。但万一代码没走到删除逻辑呢?缓存就变成了脏数据。
用CDC可以优雅解决:监听数据库的变更事件,一旦发现某条记录被更新,自动触发缓存失效。这样即使业务代码有bug,缓存也能保持最终一致。
我的经验:CDC做缓存失效,比双写模式靠谱得多。我曾经在一个金融项目里用Canal监听MySQL binlog,配合Redis的key过期策略,把缓存一致性问题从“经常出bug”降到了“几乎没出过问题”。
1.3 CDC主流工具对比
市面上CDC工具不少,我挑四个最常用的:Debezium、Canal、Maxwell、Flink CDC。下面这张表可以快速看清它们的差异。
| 特性 | Debezium | Canal | Maxwell | Flink CDC |
|---|---|---|---|---|
| 开发方 | Red Hat | 阿里巴巴 | Zendesk | Apache Flink 社区 |
| 核心原理 | 解析binlog/WAL | 解析MySQL binlog | 解析MySQL binlog | 基于Debezium + Flink |
| 支持数据库 | MySQL、PostgreSQL、MongoDB、Oracle、SQL Server等 | 仅MySQL | 仅MySQL | MySQL、PostgreSQL、MongoDB等 |
| 输出格式 | Kafka Connect(JSON/Avro) | 自定义TCP/适配Kafka | JSON(直接输出到Kafka/Redis等) | DataStream / Table API |
| 全量+增量 | 支持(Snapshot + 增量) | 需自行实现 | 支持(bootstrap) | 原生支持(全量+增量无缝切换) |
| 社区活跃度 | 极高 | 高 | 中等 | 极高 |
| 部署复杂度 | 中等(依赖Kafka Connect) | 低 | 低 | 中等(依赖Flink集群) |
1.3.1 Debezium:CDC界的“瑞士军刀”
Debezium是我个人最常用的工具。它基于Kafka Connect架构,天然适合构建流式数据管道。支持多种数据库,输出格式规范,社区非常活跃。
它的核心优势是:把数据库的每一次变更封装成一个标准事件,包含before、after、op(操作类型)、ts_ms(时间戳)等字段。下游消费者拿到这个事件,就知道发生了什么变更。
举个例子,Debezium输出的变更事件长这样:
{
"before": null,
"after": {
"id": 1001,
"name": "商品A",
"price": 29.9
},
"source": {
"db": "ecommerce",
"table": "product",
"ts_ms": 1700000000000
},
"op": "c",
"ts_ms": 1700000001000
}
op字段里,c代表create,u代表update,d代表delete。一目了然。
注意:Debezium依赖Kafka,如果你的团队没有Kafka基础设施,部署成本会偏高。小团队可以考虑Canal或Maxwell,更轻量。
1.3.2 Canal:阿里出品,MySQL专属
Canal是阿里巴巴开源的MySQL binlog解析工具。它的定位很纯粹:只做MySQL,但做得非常深。
我早期在阿里云上做项目时用过Canal。它的优点是部署简单,一个jar包就能跑起来,支持直接投递到Kafka、RocketMQ或者自定义TCP。缺点也很明显:只支持MySQL,而且全量同步需要自己写代码。
如果你只需要同步MySQL,而且团队对Java生态熟悉,Canal是个不错的选择。
1.3.3 Maxwell:轻量级选手
Maxwell是一个用Java写的MySQL CDC工具,输出格式是纯JSON。它可以直接把变更事件写入Kafka、Redis、RabbitMQ、甚至标准输出。
Maxwell最大的特点是轻量。它不需要Kafka Connect这样的重型框架,一个进程就能跑。我见过一些中小团队用Maxwell + Kafka做简单的数据同步,效果不错。
但它的功能相对单一,不支持多数据库,也不支持复杂的转换逻辑。适合“开箱即用”的场景。
1.3.4 Flink CDC:流批一体的“新贵”
Flink CDC是近年来崛起的明星。它底层基于Debezium,但把CDC能力封装成了Flink的Source算子。这意味着你可以用Flink SQL直接读取数据库的变更流。
它的杀手锏是全量+增量无缝切换。传统CDC工具做全量同步时,需要先锁表做快照,再追增量。Flink CDC通过“全量阶段先读快照,同时记录binlog偏移量,快照读完再切到增量”的方式,做到了对业务几乎无感知。
我在一个实时数仓项目里用过Flink CDC,从MySQL同步到ClickHouse,全量阶段跑了2亿条数据,增量阶段延迟控制在1秒以内。体验非常好。
我的建议:如果你已经在用Flink做流处理,Flink CDC是首选。如果你需要多数据库支持且团队有Kafka,选Debezium。如果只是MySQL单库同步且追求轻量,Canal或Maxwell都行。
1.4 一张图看懂CDC核心逻辑
下面这张SVG图展示了CDC的核心工作流程:从数据库日志捕获变更,经过解析和格式化,最终推送到下游系统。
1.5 选型避坑指南
最后,我结合自己的踩坑经历,给几点选型建议。
- 不要盲目追求“全功能”:如果你的场景只是MySQL到ES的简单同步,Canal或Maxwell就够了。上Debezium+Kafka反而增加运维成本。
- 注意binlog格式:MySQL的binlog有三种格式:STATEMENT、ROW、MIXED。CDC工具必须用ROW格式才能捕获到完整的数据变更。我曾经遇到一个项目,DBA把binlog设成了STATEMENT格式,CDC工具直接罢工。
- 全量同步的坑:很多CDC工具的全量同步阶段会锁表。生产环境一定要评估锁表的影响。Flink CDC在这方面做得最好,但也要注意大表的快照时间。
- 监控不能少:CDC链路一旦断了,数据延迟会越来越大。我建议对CDC工具做延迟监控,延迟超过阈值就告警。别问我怎么知道的——有一次Canal进程挂了三天没人发现,业务方投诉数据对不上,我背了锅。
一句话总结:CDC是实时数据架构的“地基”。选对工具,后面的事就顺了。选错了,后面全是坑。