1. CDC概念与场景:什么是CDC、CDC的应用场景、CDC主流方案对比

大家好,我是老张。做数据这行十几年了,今天咱们聊聊CDC——Change Data Capture,中文叫变更数据捕获。

说白了,CDC就是一套技术,专门用来捕获数据库里的数据变化。你往MySQL里插了一条记录,或者改了一个字段值,CDC能实时把这些变化抓出来,然后推给下游系统。嗯,就这么简单。

我记得刚入行那会儿,做数据同步全靠定时跑批。每天凌晨跑一次,数据延迟至少一天。后来业务方受不了了,说“我要看实时的订单数据”。那时候才开始接触CDC,一用就回不去了。

核心一句话:CDC = 监听数据库变更 + 实时推送变更事件。

1.1 CDC的应用场景

CDC能干什么?我列三个最常见的场景,都是我在项目中亲手做过的。

场景一:实时数仓

这是目前最火的方向。传统数仓用T+1的方式,每天凌晨从业务库拉数据。但业务方现在要的是分钟级甚至秒级的数据。

怎么做?用CDC把MySQL、Oracle的变更实时同步到Kafka,然后Flink消费Kafka,写入数仓。这样数仓里的数据就跟业务库几乎同步了。

我之前帮一家电商公司搭实时数仓,订单表每秒变更上千次。用CDC+Flink的方案,端到端延迟控制在3秒以内。业务方直呼“牛逼”。

场景二:缓存同步

很多系统用Redis做缓存,但缓存和数据库之间经常不一致。比如用户改了密码,数据库更新了,Redis里还是旧密码。

用CDC就能解决这个问题。数据库一变更,CDC捕获到,然后触发缓存更新。我做过一个项目,用Canal监听MySQL的binlog,变更后自动刷新Redis。从那以后,再也没接到过“密码不对”的投诉。

场景三:数据迁移

系统升级、数据库迁移,这些活儿大家都干过。传统做法是停机维护,把数据全量导出再导入。但停机时间越长,业务损失越大。

用CDC可以做到不停机迁移。先做一次全量同步,然后CDC持续捕获增量变更,等增量追平了,直接切换。整个过程业务无感知。

我去年帮一个金融客户做Oracle到MySQL的迁移,就是用这个方案。切换那天晚上,我盯着监控,心跳加速。结果一切顺利,零故障。

我的经验:CDC最适合的场景是“既要实时性,又要一致性”。如果业务能接受分钟级延迟,那用定时任务更简单。但如果你要秒级响应,CDC是唯一选择。

1.2 CDC主流方案对比

市面上CDC方案不少,我挑三个最主流的:Canal、Debezium、Flink CDC。这三个我都用过,各有优劣。

先看一张对比表,后面我再细说。

特性 Canal Debezium Flink CDC
数据源 MySQL(主要) MySQL、PostgreSQL、MongoDB、Oracle等 MySQL、PostgreSQL、MongoDB、Oracle、SqlServer等
底层原理 模拟MySQL Slave,解析binlog 基于Kafka Connect,解析binlog/WAL 基于Debezium,封装为Flink Source
输出方式 直接推送到客户端或MQ 写入Kafka Topic Flink DataStream/Table
断点续传 支持(基于position) 支持(基于offset) 支持(基于offset + 状态后端)
全量+增量 需自行实现 需借助Kafka Connect 原生支持(snapshot + streaming)
学习成本 低 中 中高(需熟悉Flink)
社区活跃度 中(阿里开源) 高(Red Hat) 高(Apache Flink生态)

Canal:轻量级,但生态有限

Canal是阿里巴巴开源的,专门针对MySQL。原理很简单:伪装成MySQL的从库,拉取binlog。

优点是什么?部署简单,配置少,上手快。我第一个CDC项目用的就是Canal,半天就搭起来了。

缺点也很明显:只支持MySQL。如果你要同步PostgreSQL或者Oracle,Canal就无能为力了。另外,Canal本身不提供全量同步能力,你得自己写代码做全量+增量的衔接。

避坑指南:我曾经用Canal同步一个千万级的大表,结果binlog解析速度跟不上写入速度,导致延迟越来越大。后来加了MQ做缓冲才解决。所以,高并发场景下,Canal一定要配合Kafka或RocketMQ使用。

Debezium:多数据源,强一致性

Debezium是Red Hat开源的,基于Kafka Connect框架。它支持的数据源比Canal多得多:MySQL、PostgreSQL、MongoDB、Oracle、SqlServer……基本上主流数据库都覆盖了。

Debezium的亮点是数据一致性。它保证每条变更记录只输出一次(exactly-once),不会丢数据。这一点在金融场景里特别重要。

但Debezium也有门槛。你得先搭一套Kafka集群,然后配置Kafka Connect。对于不熟悉Kafka的团队来说,运维成本不低。

我记得有一次帮客户排查Debezium的问题,发现Kafka Connect的offset提交失败,导致重复消费。查了半天,最后发现是磁盘空间不够了。嗯,这种坑踩过一次就记住了。

Flink CDC:全量+增量一体化

Flink CDC是Apache Flink生态的一部分,底层其实封装了Debezium。但它最大的优势是:原生支持全量+增量一体化同步。

什么意思?你不需要自己写全量同步的逻辑,也不需要手动做全量和增量的切换。Flink CDC自动帮你搞定:先做一次快照(snapshot),然后无缝切换到实时流。

这一点太香了。我之前用Canal做全量+增量,得写一堆胶水代码。用Flink CDC,一个Source算子就搞定了。

另外,Flink CDC天然继承了Flink的状态管理和容错机制。任务挂了,自动从checkpoint恢复,不会丢数据,也不会重复消费。

我的选择:如果项目里已经用了Flink,那Flink CDC是首选。如果只是简单同步MySQL到MQ,Canal更轻量。如果数据源多且需要强一致性,Debezium更合适。

1.3 CDC核心流程:一张图看懂

说了这么多,咱们用一张图把CDC的核心流程串起来。这是我画的一张简化图,涵盖了从数据源到目标端的完整链路。

CDC核心流程:从数据源到目标端 数据源 MySQL / Oracle / PG CDC组件 Canal / Debezium / Flink CDC 消息队列 Kafka / Pulsar 目标端 数仓 / 缓存 / 其他DB CDC组件内部工作流程 1. 连接数据源 模拟Slave / 订阅WAL 2. 解析变更日志 binlog / WAL → 事件 3. 序列化事件 JSON / Avro / Protobuf 4. 发送到下游 MQ / Flink / 直接写入 关键说明: • 全量同步(Snapshot):首次启动时,CDC组件先读取数据源的当前快照,记录所有存量数据。 • 增量同步(Streaming):快照完成后,自动切换到实时流模式,持续捕获后续变更。 • 断点续传:CDC组件会记录消费位置(binlog position / offset),任务重启后从断点继续。

这张图展示了CDC的完整链路。从左到右:数据源 → CDC组件 → 消息队列 → 目标端。CDC组件内部又分四步:连接、解析、序列化、发送。

你可能会问:为什么中间要加一个消息队列?直接写到目标端不行吗?

嗯,理论上可以。但实际项目中,加一层MQ有三大好处:

  • 解耦:CDC组件只管生产数据,下游系统自己消费。互不影响。
  • 缓冲:数据源写入峰值时,MQ能扛住压力,下游慢慢消费。
  • 多路复用:一份变更数据,可以同时供给实时数仓、缓存、搜索引擎等多个系统。

我的建议:除非你的场景特别简单(比如单机同步),否则一定要加MQ。我见过太多人为了省事直接写目标端,结果数据源一压测,下游直接被打挂。

1.4 小结

这一章咱们聊了CDC的基本概念、三大应用场景,以及Canal、Debezium、Flink CDC三个主流方案的对比。

总结一下:

  • CDC的核心是捕获数据库变更,实时推给下游。
  • 应用场景包括实时数仓、缓存同步、数据迁移,核心价值是“实时”和“一致”。
  • 方案选择上:Canal轻量但只支持MySQL,Debezium多源但依赖Kafka,Flink CDC全量增量一体化但需要Flink基础。