1. CDC概念与场景
说实话,CDC 这个概念我第一次接触是在 2016 年。当时公司要做实时数仓,业务方要求数据延迟不能超过 5 分钟。我心想,这怎么可能?传统 ETL 跑一次至少半小时。后来才接触到 CDC,说白了就是「监听数据库的变更日志,把增删改操作实时抓出来」。
CDC 的全称是 Change Data Capture,变更数据捕获。它的核心思路很简单:不去全量扫描表,而是直接从数据库的事务日志里读取变更记录。这样既不影响源库性能,又能做到秒级延迟。
一句话总结:CDC 就是数据库的「监控摄像头」,记录每一行数据的来龙去脉。
1.1 CDC 的典型应用场景
我在项目中遇到过三个最常见的场景,几乎覆盖了 CDC 90% 的用途。
场景一:数据同步
这是最基础的应用。比如你有 MySQL 业务库,想同步到 ClickHouse 做分析。用 CDC 可以做到:
- 源库插入一条订单 → 目标库秒级出现
- 源库修改用户手机号 → 目标库自动更新
- 源库删除过期数据 → 目标库同步删除
我曾经帮一家电商公司做 MySQL → Kafka → Hudi 的同步链路,上线后延迟稳定在 3 秒以内。相比他们之前每天凌晨跑一次全量同步,体验完全不一样。
场景二:实时数仓
实时数仓是 CDC 的「高光时刻」。传统数仓 T+1 出报表,实时数仓要求分钟级甚至秒级。CDC 在这里扮演的角色是「实时采集器」:
- 业务库的变更 → CDC 捕获 → 写入消息队列 → 流计算引擎处理 → 写入湖仓
- 整个过程是流式的,不需要调度任务
嗯,这里要注意:实时数仓不是把 CDC 数据直接丢进去就完事了。你还需要处理乱序、去重、回撤等问题。后面章节我会详细讲。
场景三:缓存失效
这个场景很多人容易忽略。比如你用 Redis 缓存用户信息,用户改了手机号,怎么让缓存失效?
- 传统做法:业务代码里手动删缓存。但容易漏掉,导致脏数据。
- CDC 做法:监听用户表的 UPDATE 事件,自动触发缓存失效。
我之前在一个社交平台项目里就用 CDC 做缓存失效。用户改头像后,CDN 缓存和 Redis 缓存同时失效,延迟不到 1 秒。业务方完全不用操心缓存一致性。
1.2 CDC 与批量 ETL 的对比
很多人问我:「CDC 是不是要取代 ETL?」我的回答是:不是取代,是互补。但两者的设计思路完全不同。
| 对比维度 | CDC 方式 | 批量 ETL 方式 |
|---|---|---|
| 数据延迟 | 秒级~分钟级 | 小时级~天级 |
| 源库压力 | 极低(读日志) | 较高(全表扫描) |
| 数据一致性 | 最终一致(需处理乱序) | 强一致(事务边界清晰) |
| 实现复杂度 | 较高(需处理断流、回滚) | 较低(定时调度即可) |
| 适用场景 | 实时报表、缓存失效、事件驱动 | 历史数据归档、全量初始化 |
| 运维成本 | 需监控延迟、日志位置 | 需监控任务失败重跑 |
我的建议:不要一上来就全量上 CDC。先评估业务对延迟的真实需求。如果报表 T+1 就能接受,没必要上 CDC。如果业务方说「我要实时」,那你得问清楚:是秒级还是分钟级?这决定了技术选型。
1.3 CDC 的核心工作原理
你想想看,CDC 是怎么知道数据变了?主要有两种方式:
- 基于日志的 CDC:读取数据库的 binlog(MySQL)、WAL(PostgreSQL)、Redo Log(Oracle)。这是主流方式,性能最好。
- 基于触发器的 CDC:在表上建触发器,记录变更到审计表。这种方式对源库性能影响大,现在用得少了。
我个人习惯用基于日志的方式。以 MySQL 为例,binlog 里记录了每一条 INSERT、UPDATE、DELETE 的原始数据。CDC 工具(比如 Debezium、Canal)解析 binlog,输出成统一格式的事件流。
我曾经踩过一个坑:binlog 格式没配好。MySQL 默认是 STATEMENT 格式,只记录 SQL 语句。但 CDC 需要 ROW 格式,才能拿到变更前后的具体数据。那次排查了整整半天,最后发现是 DBA 没开 ROW 模式。所以,用 CDC 之前,一定确认数据库的日志格式。
避坑指南:我曾经遇到过 CDC 断流后重新同步,数据出现重复。原因是 binlog 的 offset 没记录对。建议在生产环境里,把 binlog 的位点信息持久化到外部存储(比如 ZooKeeper 或数据库),不要只存在内存里。
1.4 CDC 在 Lakehouse 架构中的位置
这张图展示了 CDC 在整个 Lakehouse 数据流中的核心位置:
从这张图你能看到,CDC 是整个实时链路的「起点」。没有 CDC,后面的流计算和 Lakehouse 都只能处理静态数据。我经常跟团队说:CDC 做不好,实时数仓就是空中楼阁。
1.5 什么时候该用 CDC?
最后,我总结一下 CDC 的适用条件。不是所有场景都适合 CDC:
- 适合用 CDC:数据量大、变更频繁、对延迟敏感、需要事件驱动
- 不适合用 CDC:数据量小、变更极少、对实时性没要求、源库是只读库
举个例子:用户行为日志(点击、浏览)不适合用 CDC,因为它是 append-only 的,用消息队列直接采集更简单。但订单状态变更、用户信息修改这类场景,CDC 就是最佳选择。
一个小技巧:如果你不确定要不要上 CDC,可以先做一次「变更频率评估」。统计源库每天有多少条 INSERT/UPDATE/DELETE。如果日变更量在百万级以下,用批量 ETL 加短周期调度也能凑合。如果千万级以上,CDC 几乎是唯一选择。