一、CDC技术概述:从数据库日志到实时数据湖
大家好,我是这次课程的主讲。做了十几年数据架构,我越来越觉得,CDC(Change Data Capture)是构建实时数据湖的基石。说白了,CDC就是一种捕获数据变化的技术——它能实时监听数据库里的增、删、改操作,然后把变化同步到其他系统。
你想想看,传统的数据同步方式,要么是定时跑批(比如每天凌晨全量同步一次),要么是业务双写。前者延迟高,后者侵入性强。CDC的出现,算是把这两大痛点都解决了。
1.1 什么是CDC?
CDC的全称是Change Data Capture,中文叫“变更数据捕获”。它的核心思想很简单:让数据消费者能够实时感知到数据源的变化。
我记得2016年刚接触这个技术时,团队还在用定时任务拉取增量数据。每次跑批都要停服务,用户体验很差。后来引入CDC,延迟从小时级降到了秒级。嗯,这里要注意,CDC不是银弹,但它确实改变了实时计算的玩法。
CDC的核心价值: 将数据库的增量变更,以事件流的形式实时推送给下游系统。数据湖、缓存、搜索引擎、消息队列,都能从中受益。
1.2 CDC的三种主流实现方式
CDC的实现方式有很多种,但主流的就三种:基于日志、基于触发器、基于时间戳。我一个个说,顺便聊聊我在项目里踩过的坑。
1.2.1 基于日志的CDC(Log-Based CDC)
这是目前最推荐的方式。它直接读取数据库的事务日志(比如MySQL的binlog、PostgreSQL的WAL、Oracle的Redo Log),解析出数据变更事件。
工作原理:
- 数据库每次提交事务,都会把变更记录写入日志文件
- CDC工具(如Debezium、Canal、Maxwell)模拟成从库,实时拉取日志
- 解析日志中的INSERT、UPDATE、DELETE事件,输出为结构化消息
优点:
- 对源库零侵入,不需要改表结构或加触发器
- 延迟极低,毫秒级捕获
- 能捕获所有变更,包括DDL操作
缺点:
- 需要数据库开启日志功能(默认一般都开着)
- 日志格式解析复杂,不同数据库的日志格式差异很大
我的经验: 我个人习惯优先选择基于日志的CDC。曾经有个项目,业务方要求数据延迟不超过5秒,用基于日志的方案轻松搞定。如果选其他方式,延迟根本压不下来。
1.2.2 基于触发器的CDC(Trigger-Based CDC)
这种方式是在源数据库上创建触发器,当表发生INSERT、UPDATE、DELETE时,触发器把变更记录写入一张专门的审计表或日志表。
工作原理:
- 在需要监听的表上创建AFTER INSERT/UPDATE/DELETE触发器
- 触发器将变更数据写入变更记录表
- CDC程序定期或实时从变更记录表读取数据
优点:
- 实现简单,不依赖数据库日志格式
- 可以自定义捕获哪些字段、哪些操作
缺点:
- 对源库性能有影响——每次DML操作都要额外执行触发器逻辑
- 侵入性强,需要修改数据库对象
- 触发器本身可能成为故障点
避坑指南: 我曾经在一个高并发交易系统里用过触发器CDC,结果数据库负载直接飙升了30%。后来紧急切回了基于日志的方案。触发器方案只适合低并发、对侵入性不敏感的场景。
1.2.3 基于时间戳的CDC(Timestamp-Based CDC)
这种方式依赖业务表中的时间戳字段(如update_time、modified_at),通过定时查询“大于上次同步时间戳”的数据来获取增量。
工作原理:
- 业务表必须包含最后修改时间字段
- CDC程序定期执行
SELECT * FROM table WHERE update_time > last_sync_time - 将查询结果作为增量数据发送给下游
优点:
- 实现最简单,不需要额外组件
- 对数据库无侵入
缺点:
- 无法捕获DELETE操作(除非用软删除)
- 时间戳精度问题——同一毫秒内的多次变更可能漏掉
- 延迟取决于轮询频率,做不到真正的实时
我的建议: 时间戳CDC只适合对实时性要求不高的场景,比如小时级的数据同步。如果你要做实时数据湖,千万别用这个方案——漏数据是迟早的事。
1.3 三种CDC实现方式的对比
我把三种方式的核心差异整理成了表格,方便你对比选型:
| 对比维度 | 基于日志 | 基于触发器 | 基于时间戳 |
|---|---|---|---|
| 实时性 | 毫秒级 | 秒级 | 分钟级(取决于轮询间隔) |
| 源库侵入性 | 无 | 高(需创建触发器) | 低(需时间戳字段) |
| 性能影响 | 极小 | 较大 | 取决于查询频率 |
| 捕获完整性 | 全部变更(含DDL) | 全部DML变更 | 无法捕获DELETE |
| 实现复杂度 | 高 | 中 | 低 |
| 适用场景 | 实时数据湖、实时数仓 | 低并发、可接受侵入 | 离线同步、非关键链路 |
1.4 CDC在实时数据湖中的核心价值
说到实时数据湖,很多人第一反应是“把数据实时写入HDFS或对象存储”。但真正的实时数据湖,远不止写入这么简单。CDC在其中扮演了四个关键角色:
- 实时增量入湖:传统方式全量导入耗时耗资源,CDC只传输增量变更,带宽和计算成本大幅降低。
- 保证数据一致性:基于日志的CDC能保证“至少一次”或“精确一次”语义,不会丢数据也不会重复。
- 支持数据回放:CDC输出的变更事件流可以持久化到消息队列(如Kafka),需要时可以从任意时间点回放历史变更。
- 解耦数据源与数据湖:CDC作为中间层,数据源(MySQL、PostgreSQL等)不需要感知数据湖的存在,业务系统零改造。
一句话总结: CDC让数据湖从“T+1的离线仓库”变成了“秒级响应的实时引擎”。没有CDC,实时数据湖就是空中楼阁。
1.5 CDC在实时数据湖中的核心逻辑
下面这张图展示了CDC在实时数据湖中的核心位置和流转逻辑。我画的时候特意把数据源、CDC组件、消息队列、数据湖引擎这几个关键节点都标出来了:
从这张图你能看到,CDC组件处于整个数据链路的核心位置。它从数据库日志中捕获变更,推送到消息队列,再由消息队列写入数据湖。数据湖引擎(如Apache Hudi、Iceberg)负责管理文件版本和事务,计算引擎(如Flink)则对湖内数据进行实时分析。
我的经验: 在实际项目中,我习惯把CDC组件和消息队列部署在同一台物理机或同一个K8s集群上,减少网络延迟。曾经有个客户把CDC部署在跨地域的机房,结果延迟飙到了200ms,后来调整架构才解决。
1.6 本章小结
这一章我们聊了CDC的基本概念、三种主流实现方式,以及它在实时数据湖中的核心价值。说白了,CDC就是实时数据湖的“眼睛”和“耳朵”——没有它,数据湖就是个聋子瞎子,只能被动接收定时投喂的数据。