1. CDC 概念与原理:从数据变化说起

大家好,我是这次课程的主讲。今天咱们聊聊 CDC——Change Data Capture,中文叫「变更数据捕获」。这名字听起来挺唬人,说白了就是:监控数据库里的数据什么时候变了,然后把变化抓出来。

我记得刚入行那会儿,做数据同步还在用「全量跑批」的方式。每天晚上凌晨跑一次,把整个表导过去。数据量一大,跑批时间越来越长,业务方早上来了发现数据还是昨天的。嗯,那时候我就想:能不能只同步变化的部分?CDC 就是干这个的。

什么是 CDC?

CDC 的核心思想很简单:不扫描全表,只捕获增量变化。你想想看,一个订单表几千万行,每天新增的可能就几千行。全量扫描一次,CPU、IO、网络全吃满,何必呢?

CDC 的价值在于:

  • 实时性高:数据变化后毫秒级就能感知
  • 资源消耗低:只处理变化的数据,不碰历史数据
  • 对源库影响小:不需要频繁全表扫描

一句话总结:CDC 就是数据库的「变化监听器」,谁改了数据,它第一时间知道。

CDC 的三种常见实现方式

实现 CDC 的方式有好几种,我挑最主流的三个来讲。每种都有它的适用场景,也有各自的坑。

1. 基于日志的 CDC(Log-based CDC)

这是目前最推荐的方式,也是 Flink CDC 底层用的方案。原理是读取数据库的事务日志——比如 MySQL 的 binlog、PostgreSQL 的 WAL、Oracle 的 Redo Log。

数据库每执行一条 INSERT、UPDATE、DELETE,都会先写日志,再落盘。CDC 工具直接读这个日志,就能拿到完整的变化记录。

优点:

  • 对源库零侵入,不需要改表结构
  • 能捕获所有变更,包括 DELETE 和旧值
  • 延迟极低,毫秒级

缺点:

  • 需要数据库开启日志功能(默认一般都开着)
  • 日志格式各厂商不同,解析有门槛
  • 日志有保留期限,过期就抓不到了

我的经验:我在项目中遇到过 binlog 被清理导致数据断流的情况。后来我养成了一个习惯——每次上线前先检查 binlog 保留天数,至少设 7 天以上。

2. 基于触发器的 CDC(Trigger-based CDC)

在数据库表上创建触发器,当数据发生变化时,触发器把变化记录写入一张专门的「变更日志表」。然后 CDC 工具去读这张表。

这种做法在早期很常见,但现在我基本不推荐了。为什么?

  • 性能开销大:每次 DML 操作都要额外执行触发器逻辑
  • 影响源库:触发器失败会导致主操作也失败
  • 维护麻烦:改表结构时触发器也要跟着改

避坑指南:我曾经在一个高并发订单系统里见过触发器 CDC,结果业务高峰期数据库直接被打挂了。触发器本身成了瓶颈。从那以后,我对触发器方案就敬而远之了。

3. 基于时间戳的 CDC(Timestamp-based CDC)

在表里加一个 last_modified 或 update_time 字段,每次更新时更新这个时间戳。CDC 工具定期查询「时间戳大于上次同步时间」的数据。

这算是最「朴素」的 CDC 实现。简单,但问题也不少:

  • 无法捕获 DELETE:删了数据,时间戳字段也没了
  • 依赖业务代码:必须保证每条更新都正确设置时间戳
  • 延迟较高:轮询间隔决定了实时性

不过,如果业务对实时性要求不高,且数据量不大,这个方案也能用。我见过一些报表系统就是这么干的。

三种方式对比

特性 基于日志 基于触发器 基于时间戳
对源库影响 低 高 中
实时性 毫秒级 毫秒级 秒~分级
能否捕获 DELETE 能 能 不能
能否捕获旧值 能 需额外配置 不能
维护成本 低 高 中
推荐场景 实时数仓、数据同步 不推荐 低要求报表

CDC 在实时数据管道中的价值

说完了概念和实现,咱们聊聊 CDC 到底能解决什么问题。我把它总结为三个核心价值:

  1. 打破数据孤岛:业务数据在 MySQL 里,分析在 ClickHouse 里,搜索在 Elasticsearch 里。CDC 能把变化实时同步到各个系统,不用再手动导数据。
  2. 降低延迟:传统 ETL 是 T+1,CDC 能做到秒级甚至毫秒级。业务方看到的永远是「现在」的数据。
  3. 减少全量压力:只同步增量,源库和目标的负载都大幅降低。说白了,就是花更少的钱,干更多的活。

举个例子:电商大促期间,订单数据实时同步到实时数仓,运营后台能看到实时的 GMV、订单量、退款率。没有 CDC,这些数据只能第二天看,黄花菜都凉了。

CDC 核心流程示意图

下面这张图展示了 CDC 在实时数据管道中的位置和工作流程。我画得比较简洁,但核心链路都在了。

CDC 实时数据管道核心流程 CDC 实时数据管道核心流程 源数据库 MySQL / PostgreSQL / Oracle 事务日志 binlog / WAL / Redo Log 写入 CDC 捕获器 Flink CDC / Debezium / Canal 读取解析 消息队列 Kafka / Pulsar / RocketMQ 发送 目标系统 实时数仓 / ES / Redis 消费写入 💡 说明 1. 源数据库写入事务日志,CDC 工具实时读取日志解析变更事件。 2. 变更事件发送到消息队列解耦,下游消费者按需拉取。 3. 目标系统消费消息,完成数据同步。整个过程端到端延迟通常在秒级以内。

小结

这一章咱们把 CDC 的概念、三种实现方式、以及在实时管道中的价值都过了一遍。说白了,CDC 就是实时数据管道的「眼睛」——没有它,你根本不知道数据什么时候变了。