一、CDC 技术概述:到底什么是 CDC?

CDC,全称 Change Data Capture,中文叫「变更数据捕获」。说白了,就是实时监听数据库里的数据变化——哪条记录被插入了、哪条被更新了、哪条被删除了——然后把这些变化抓出来,同步到别的地方去。

我刚开始接触这个概念时,觉得它不就是个「数据库监听器」嘛。后来在项目中踩过几次坑才明白,CDC 远不止监听那么简单。它要解决的是:如何低延迟、不侵入、不丢数据地捕获变化。这三个点,任何一个没做好,生产环境就会出大问题。

核心定义:CDC 是一种通过读取数据库的变更记录(如 Binlog、WAL、触发器日志),实时捕获数据变化并推送给下游系统的技术方案。它不是简单的轮询对比,而是「事件驱动」的数据同步模式。

1.1 为什么需要 CDC?—— 三个典型场景

你可能要问:数据同步有很多方式,为什么非要 CDC?我拿三个最常见的场景来说说。

场景一:数据仓库实时入仓

传统做法是每天凌晨跑批处理,用 ETL 把数据从业务库抽到数仓。但问题是——延迟太大了。早上 8 点的订单,要等到第二天凌晨才能分析,这在实时报表、风控场景下根本没法用。

CDC 的做法是:业务库每产生一条变更,CDC 组件立刻捕获,毫秒级推送到 Kafka,数仓实时消费。我在某电商公司做过一个项目,把 T+1 的离线报表改成了 CDC 实时入仓,延迟从 24 小时降到了 3 秒以内。嗯,业务方当时都惊了。

场景二:微服务数据一致性

微服务架构下,每个服务有自己的数据库。订单服务改了订单状态,库存服务、物流服务都需要知道。如果靠应用层发消息通知,很容易出现消息丢失、重复消费、顺序错乱的问题。

CDC 可以充当「可靠的事件总线」:订单库的变更被 CDC 捕获后,直接转成领域事件推送给其他服务。我曾经帮一个团队重构过他们的订单同步方案,之前用 MQ 手动发消息,经常丢单;换成 CDC 后,再也没有出现过数据不一致的投诉。

场景三:缓存与搜索引擎同步

Redis 缓存、Elasticsearch 搜索引擎,它们的数据源通常是关系型数据库。数据库里的商品信息改了,缓存和 ES 也得跟着更新。如果靠业务代码双写,不仅侵入性强,还容易漏写。

CDC 可以做到:数据库变更 → 捕获 → 推送到 Redis/ES,全程无代码侵入。我个人习惯把这种模式叫做「旁路同步」——业务方完全感知不到同步的存在。

应用场景 传统方案痛点 CDC 方案优势
数据仓库 T+1 延迟,无法实时分析 毫秒级入仓,实时报表
微服务 消息丢失、顺序错乱 可靠事件溯源,Exactly-Once
缓存/搜索引擎 代码侵入,双写不一致 旁路同步,零侵入

1.2 CDC 的三种核心模式

CDC 不是只有一种实现方式。根据捕获数据变更的原理不同,我把它分成三类:基于日志、基于轮询、基于触发器。每种模式都有各自的优缺点,选型时一定要结合业务场景。

模式一:基于日志(Log-Based)

这是目前最主流、性能最好的 CDC 模式。原理很简单:数据库在写入数据时,会同时记录事务日志(比如 MySQL 的 Binlog、PostgreSQL 的 WAL、Oracle 的 Redo Log)。CDC 工具直接读取这些日志,解析出变更事件。

优点很明显:对业务库零侵入,不需要改表结构、不需要加触发器,性能损耗极小。我在生产环境中用过 Debezium + Kafka 的组合,单机吞吐量能到每秒几万条变更,延迟在毫秒级。

但要注意一点:日志格式是数据库厂商私有的,不同数据库的解析方式完全不同。MySQL 的 Binlog 有 Row、Statement、Mixed 三种格式,我建议生产环境必须用 Row 格式,否则捕获到的数据可能不完整。

我的经验:基于日志的 CDC 是首选方案。如果你的数据库支持 Binlog 或 WAL,优先选这个模式。但要注意日志保留期——我曾经因为 Binlog 过期被自动清理,导致 CDC 断流,重建了整整 6 小时的同步任务。现在我的习惯是:Binlog 保留至少 72 小时。

模式二:基于轮询(Polling-Based)

这种模式不依赖数据库日志,而是通过定期执行 SQL 查询来发现变更。常见做法是在表中增加 last_modified 时间戳字段,每次轮询时查询「修改时间 > 上次轮询时间」的数据。

听起来简单,但坑很多。我举个例子:如果业务系统没有统一维护时间戳字段,或者时间戳精度不够(比如只到秒级),同一秒内的多次变更就可能漏掉。更麻烦的是,删除操作无法通过轮询捕获——除非你改用软删除。

轮询模式适合什么场景?数据量小、变更频率低、对实时性要求不高的系统。比如每天同步一次配置表,用轮询完全够用。但如果是高并发交易系统,我建议你直接放弃轮询。

避坑指南:我曾经在一个项目中用轮询同步订单表,每秒查询一次。结果业务高峰期数据库 CPU 直接飙到 90%,DBA 差点把我拉黑。后来改成基于日志的 CDC,CPU 占用降到了 5%。轮询的代价是:查询频率越高,对数据库的压力越大。

模式三:基于触发器(Trigger-Based)

触发器是数据库内置的功能:在表上创建 INSERT、UPDATE、DELETE 触发器,当数据变更时,触发器把变更记录写入一张专门的日志表。CDC 工具再去读取这张日志表。

这种模式的优点是:兼容性好,几乎所有的关系型数据库都支持触发器。而且可以捕获删除操作(不像轮询那样需要软删除)。

但缺点也很致命:对业务库性能影响大。每次 DML 操作都要额外执行一次触发器写入,在高并发场景下,这个开销不可忽视。我见过一个案例,某系统加了触发器后,写入性能下降了 30%。

另外,触发器是数据库对象,部署和运维都比较麻烦。如果你要同步 100 张表,就得创建 300 个触发器(每张表 3 个)。想想就头疼。

模式 原理 性能 侵入性 适用场景
基于日志 读取事务日志 高(毫秒级) 无 高并发、实时同步
基于轮询 定时 SQL 查询 低(秒级) 需加时间戳字段 低频、小数据量
基于触发器 触发器写日志表 中(有额外开销) 需创建触发器 兼容性要求高

1.3 三种模式如何选型?

你可能会问:这么多模式,我到底该选哪个?我个人的选型原则是:

  • 首选基于日志:只要数据库支持(MySQL、PostgreSQL、Oracle、SQL Server 都支持),无脑选日志模式。性能最好,侵入性最低。
  • 次选基于触发器:如果数据库不支持日志解析(比如某些老旧的数据库),或者你无法获取日志读取权限,触发器是备选方案。
  • 最后选轮询:只有在你无法使用日志和触发器,且数据量极小、实时性要求不高的情况下,才考虑轮询。

一句话总结:日志模式是「正规军」,触发器是「游击队」,轮询是「万不得已的备胎」。选型时优先考虑日志模式,它能帮你省掉 80% 的运维烦恼。

1.4 CDC 核心架构图

下面这张图展示了 CDC 的整体架构和三种模式的对比。你可以看到,数据源(业务数据库)通过不同的捕获方式,将变更事件推送到消息队列或直接写入目标系统。

CDC 三种核心模式架构对比 业务数据库(数据源) 模式一:基于日志 读取 Binlog / WAL 模式二:基于轮询 定时 SQL 查询 模式三:基于触发器 触发器写入日志表 消息队列(Kafka / Pulsar) 数据仓库 微服务 缓存 / ES 三种模式最终都通过消息队列解耦,将变更事件推送给不同的目标系统

1.5 小结

这一章我们聊了 CDC 的核心概念、三个典型应用场景,以及三种实现模式。说白了,CDC 就是数据库的「实时变化监听器」,它让数据同步从批处理时代进入了实时时代。

我个人建议:能上日志模式就上日志模式。这是经过生产环境验证的最佳实践。后面的章节,我会带你深入 Debezium、Canal、Flink CDC 这些具体工具,看看它们是怎么实现日志解析的。