1. CDC概念与原理:从数据变化说起
大家好,我是你们这门课的老朋友。今天咱们正式开篇,聊聊CDC——Change Data Capture,中文叫“变更数据捕获”。
说白了,CDC就是一套技术方案,用来实时或准实时地捕捉数据库里的数据变化(新增、修改、删除),然后把这些变化同步到其他系统里去。你想想看,现代数据架构里,数据源和目标端往往不是同一个库,怎么让它们保持数据一致?CDC就是那个“桥梁”。
核心一句话:CDC不是“全量搬运”,而是“增量同步”。它只关注“变了什么”,而不是“有什么”。
1.1 为什么需要CDC?——我在项目中踩过的坑
我记得刚做数据平台那会儿,团队还在用定时批处理脚本同步数据。每天凌晨跑一次全量抽取,跑完大概要两三个小时。业务方早上来一看,数据还是昨天的。后来业务要求实时性越来越高,批处理根本扛不住。
有一次,一个电商客户要求订单状态变更后5秒内同步到分析系统。我们试过用应用双写,结果代码改得一团糟,还经常漏数据。最后换成了CDC方案,问题才彻底解决。
所以,CDC的价值在哪?我总结了几点:
- 低延迟:秒级甚至毫秒级捕获变化,满足实时场景
- 无侵入:不需要改业务代码,对源库影响小
- 高可靠性:基于日志的CDC能保证“至少一次”或“精确一次”的语义
- 全量+增量一体化:先做一次快照,后续只同步增量,效率极高
我的经验:如果你还在用“定时全量覆盖”的方式做数据同步,赶紧看看CDC。尤其是数据量上了TB级别,全量抽取的成本会让你崩溃。
1.2 CDC的三种常见实现方式
CDC不是只有一种玩法。根据实现原理,我把它分成三大类。咱们一个一个说。
1.2.1 基于日志的CDC(Log-based CDC)
这是目前最主流、最推荐的方式。原理很简单:数据库的每一次数据变更,都会写入事务日志(比如MySQL的binlog、PostgreSQL的WAL、Oracle的Redo Log)。CDC工具直接读取这些日志,解析出变更事件,然后推送给下游。
我在项目中用得最多的就是这种方式。比如用Debezium监听MySQL的binlog,然后通过Kafka把变更事件流式传输到Lakehouse。
-- 示例:MySQL binlog中一条INSERT操作被解析成的事件结构(简化版)
{
"op": "c", -- c=create, u=update, d=delete
"ts_ms": 1698000000123,
"source": {
"db": "ecommerce",
"table": "orders",
"server_id": 1
},
"before": null,
"after": {
"id": 10086,
"user_id": 9527,
"amount": 299.00,
"status": "paid",
"create_time": "2023-10-23 10:00:00"
}
}
优点:对源库几乎无侵入,性能高,支持所有DML操作(包括DELETE)。
缺点:需要数据库开启日志功能,解析日志有一定技术门槛。
1.2.2 基于触发器的CDC(Trigger-based CDC)
这种方式是在源库的表上创建触发器。当数据发生INSERT、UPDATE、DELETE时,触发器自动把变更记录写入一张专门的“变更日志表”。然后另一个进程去读取这张表,把数据同步出去。
嗯,这里要注意。我早期做过一个项目就是用触发器实现的。当时觉得挺简单,后来发现坑不少。
我曾经踩过的坑:触发器会显著增加源库的写入延迟,尤其是在高并发场景下。有一次生产环境因为触发器逻辑太复杂,导致数据库写入性能下降了30%。从那以后,我基本只在数据量小、对实时性要求不高的场景下才考虑触发器。
| 对比维度 | 基于日志 | 基于触发器 | 基于时间戳 |
|---|---|---|---|
| 对源库影响 | 低(异步读取日志) | 高(同步触发) | 低(仅查询) |
| 支持DELETE | 是 | 是 | 否(只能标记删除) |
| 实时性 | 秒级/毫秒级 | 秒级 | 分钟级(取决于轮询频率) |
| 实现复杂度 | 中高 | 低 | 低 |
| 适用场景 | 大规模、高并发、实时 | 小规模、低频、简单 | 非实时、无删除、可接受延迟 |
1.2.3 基于时间戳的CDC(Timestamp-based CDC)
这种方式最“朴素”。在源表里加一个last_modified或update_time字段。同步程序定期轮询这张表,查询“时间戳大于上次同步时间”的数据,然后拉取增量。
说白了,就是“定时查表”。实现起来确实简单,但局限性也很明显。
我个人习惯:如果业务表本身就有update_time字段,而且数据量不大(百万级以内),用时间戳方式快速搭一个同步通道是可以的。但别指望它能处理DELETE操作——物理删除的数据,时间戳字段都没了,你查不到。
1.3 CDC在数据同步中的核心价值
讲完了实现方式,咱们聊聊CDC到底解决了什么问题。我把它归纳成三个层面:
- 实时性革命:从T+1到秒级。传统ETL是“定时批量”,CDC是“流式持续”。这个转变,让数据仓库从“事后分析”变成了“实时决策”。
- 数据一致性保障:基于日志的CDC能保证变更事件的顺序和完整性。不会丢数据,也不会乱序。这一点在金融、电商场景下至关重要。
- 架构解耦:源库不需要知道下游是谁。CDC工具作为中间层,把数据变更以统一格式(比如Debezium的Change Event)推送给Kafka、Pulsar等消息队列。下游的Lakehouse、实时计算引擎各取所需。
一句话总结:CDC让数据同步从“搬砖”变成了“管道”。你不需要每次把整栋楼的数据搬一遍,只需要把“变化的那几块砖”传过去就行。
1.4 一张图看懂CDC核心逻辑
下面这张SVG图,展示了CDC在数据同步中的整体流程。从源数据库到目标Lakehouse,CDC扮演了“实时搬运工”的角色。
1.5 小结:CDC不是银弹,但它是基石
好了,这一章的内容就这些。CDC的概念和原理,说白了就是“怎么高效、可靠地捕获数据变化”。三种实现方式各有优劣,我个人强烈推荐基于日志的CDC作为首选方案,尤其是当你面对大规模、高并发的生产环境时。
下一章咱们会深入Debezium这个具体的CDC工具,看看它怎么和Kafka配合,把数据实时同步到Lakehouse。不过那是后话了,先把今天的基础打牢。
课后思考:如果你现在负责一个订单系统的数据同步,每天新增100万条订单,偶尔有更新和删除。你会选择哪种CDC方式?为什么?