实时推荐CDC技术实现数据库实时同步 - 第1节

1. CDC 技术概述:什么是 CDC?

CDC,全称 Change Data Capture,中文叫「变更数据捕获」。说白了,就是一套能实时捕捉数据库里数据变化的机制。

你想想看,传统做法是定期跑批,把整张表导一遍。但 CDC 不一样——它只盯着变化的数据。插入、更新、删除,它都能抓到,然后实时推给下游。

我个人习惯把 CDC 理解成「数据库的日志订阅者」。它不直接查表,而是读数据库的日志文件。比如 MySQL 的 binlog、PostgreSQL 的 WAL、Oracle 的 Redo Log。这样对源库几乎没有性能影响。

核心要点:CDC 不是轮询,不是定时扫描。它是事件驱动的,数据一变,CDC 就感知到了。

1.1 CDC 的两种实现模式

我在项目中遇到过不少团队把这两种模式搞混,这里先理清楚。

模式 原理 典型工具 延迟
基于日志 解析数据库事务日志 Debezium、Canal、Maxwell 毫秒级
基于触发器/时间戳 在表上建触发器或维护时间戳字段 自研脚本、SymmetricDS 秒级到分钟级

基于日志的模式,是真正的实时。基于触发器的模式,对源库有侵入,性能损耗也大。我个人建议,只要条件允许,优先选基于日志的方案。

我的经验:曾经有个项目,团队用时间戳字段做增量同步。结果业务方半夜改了数据,忘了更新时间戳,第二天对账差了 200 万条记录。从那以后,我再也不推荐时间戳方案了。

2. CDC 的应用场景

CDC 能做的事,比你想象的多。我挑三个最典型的场景来讲。

2.1 数据仓库实时入仓

传统 ETL 是 T+1,每天凌晨跑批。但业务方现在要的是「秒级可见」。比如电商大促,运营要看实时 GMV,你总不能等第二天吧?

CDC 可以把 MySQL 的变更实时推给 Kafka,然后 Flink 消费写入 ClickHouse 或 StarRocks。延迟控制在 1 秒以内。

一句话总结:CDC 让数据仓库从「昨天」变成了「刚才」。

2.2 缓存更新

Redis 缓存和数据库之间的数据不一致,是很多团队的噩梦。我见过最夸张的案例:缓存过期时间设了 30 分钟,用户改了密码,30 分钟内还能用旧密码登录。

用 CDC 监听数据库的变更事件,一旦有更新,立即通知缓存失效或刷新。这样缓存和数据库就能保持最终一致。

// 伪代码:CDC 事件 -> 缓存更新
onEvent(UserUpdatedEvent event) {
    String key = "user:" + event.getUserId();
    cache.del(key);  // 删除旧缓存
    // 或者 cache.set(key, fetchFromDB(event.getUserId()));
}

注意:CDC 不是强一致性方案,它是最终一致性。如果你的业务要求强一致,CDC 不适合你。

2.3 微服务解耦

微服务之间最怕什么?服务 A 改了数据,服务 B 不知道。传统做法是服务 A 调用服务 B 的 API,但这样耦合太紧。一旦 B 挂了,A 也跟着受影响。

CDC 可以充当「数据总线」。服务 A 的数据库变更,通过 CDC 推给消息队列,服务 B 订阅自己关心的数据。两个服务完全解耦。

我曾经帮一个客户改造订单系统。原来订单服务和库存服务通过 RPC 调用,高峰期经常超时。改成 CDC 异步同步后,系统稳定性提升了 40%。

3. CDC 与 ETL 的区别

很多人把 CDC 和 ETL 混为一谈。其实它们不是替代关系,而是互补关系。

维度 CDC ETL
触发方式 事件驱动,实时 定时调度,批量
数据量 增量,单条或小批量 全量或大批量
延迟 毫秒到秒级 分钟到小时级
对源库影响 极小(读日志) 较大(全表扫描)
典型工具 Debezium, Canal, Maxwell DataX, Kettle, Informatica

你想想看,ETL 适合做什么?历史数据迁移、全量初始化、复杂的数据清洗。CDC 适合做什么?实时增量同步、事件驱动、缓存刷新。

实际项目中,我通常把两者结合使用:先用 ETL 做一次全量同步,然后 CDC 接管增量。这样既快又准。

我的建议:不要试图用 CDC 替代 ETL,也不要只用 ETL 做实时。两者配合,才是最佳实践。

4. CDC 核心架构图

下面这张图,是我自己画的一个 CDC 整体架构。它展示了数据从源库到目标系统的完整链路。

CDC 核心架构图 CDC 核心架构图 源数据库 MySQL / PostgreSQL / Oracle 事务日志 (binlog/WAL) CDC 连接器 Debezium / Canal 消息队列 Kafka / Pulsar 数据仓库 ClickHouse / StarRocks 缓存 Redis / Memcached 微服务 异步解耦消费 说明: 1. CDC 连接器读取源库事务日志,不直接查表,对源库无侵入。 2. 消息队列作为缓冲层,削峰填谷,保证数据不丢失。 3. 下游消费者按需订阅,互不影响,实现解耦。

这张图展示了 CDC 的完整链路:源库 → 日志 → CDC 连接器 → 消息队列 → 下游消费者。每个环节都有它的职责,缺一不可。

避坑指南:我曾经见过一个团队,CDC 连接器直接写目标库,中间没有消息队列。结果目标库一重启,数据全丢了。记住,消息队列是 CDC 架构的「保险丝」,别省。

5. 本章小结

CDC 不是什么新概念,但它在实时数据同步领域的地位越来越重要。我总结三个关键点:

  • CDC 是事件驱动的,不是轮询。它读日志,不查表。
  • CDC 的应用场景很广:数据仓库实时入仓、缓存更新、微服务解耦,都是它的强项。
  • CDC 和 ETL 是互补的:ETL 做全量,CDC 做增量,两者配合效果最好。

嗯,这一章就到这里。CDC 的基础概念讲清楚了,后面我们会深入具体的实现细节。