1. CDC 基础概念与数据一致性挑战
大家好,我是这次课程的主讲。做了这么多年数据工程,CDC 这块我踩过的坑还真不少。今天咱们先打好基础,聊聊 CDC 到底是什么,以及它为什么这么让人头疼。
什么是 CDC?
CDC,全称 Change Data Capture,中文叫「变更数据捕获」。说白了,就是实时监控数据库里的数据变化——谁新增了一条记录、谁修改了某个字段、谁删了一行数据,CDC 都能第一时间抓到。
我个人习惯把 CDC 比作数据库的「监控摄像头」。你想想看,业务系统每时每刻都在产生数据,但下游的数据仓库、缓存、搜索引擎需要知道这些变化才能保持同步。CDC 就是那个盯着数据库、一有风吹草动就通知下游的中间人。
核心价值:CDC 让数据从源端到目标端的同步延迟从小时级降到秒级,而且不需要业务系统做任何代码改造。
CDC 的三种主流实现方式
我在项目中见过各种 CDC 方案,但真正在生产环境站稳脚跟的,主要是下面这三种。每种都有它的脾气,选错了可是要吃苦头的。
1. 基于日志(Log-Based)
这是目前最主流、也是我个人最推荐的方式。它直接读取数据库的事务日志(比如 MySQL 的 binlog、PostgreSQL 的 WAL、Oracle 的 Redo Log),解析出数据变更事件。
- 优点:对源库几乎零侵入,不触发触发器,不增加查询压力;能捕获所有变更,包括 DELETE 操作;延迟极低,毫秒级。
- 缺点:日志格式各数据库厂商不统一,解析复杂度高;需要 DBA 配合开启日志保留策略。
我的经验:有一次客户 MySQL 的 binlog 只保留 24 小时,结果下游任务挂了 30 小时,恢复时日志已经过期了。后来我强制要求 binlog 保留至少 7 天,并且加了个监控告警。嗯,这个坑你们别踩。
2. 基于触发器(Trigger-Based)
在源库的每张表上创建触发器,当发生 INSERT、UPDATE、DELETE 时,触发器把变更记录写入一张专门的日志表。CDC 工具再去读取这张日志表。
- 优点:实现简单,不依赖数据库日志;能自定义捕获哪些字段。
- 缺点:对源库性能影响大——每个 DML 操作都要额外写一次日志表;触发器维护成本高,表结构变更时容易出问题。
避坑指南:我曾经在一个高并发订单系统上用过触发器方案,结果数据库负载直接飙升 30%。生产环境,尤其是写密集场景,慎用触发器。
3. 基于时间戳(Timestamp-Based)
在源表上增加一个「最后修改时间」字段,CDC 工具定期轮询这张表,根据时间戳筛选出增量数据。
- 优点:实现最简单,不需要额外组件;适合数据量不大的场景。
- 缺点:无法捕获 DELETE 操作(除非用软删除);时间戳精度不够时可能漏数据;轮询间隔决定了延迟下限。
这三种方式的差异,我整理了一张对比表,方便你快速参考:
| 特性 | 基于日志 | 基于触发器 | 基于时间戳 |
|---|---|---|---|
| 源库侵入性 | 低 | 高 | 中(需加字段) |
| 延迟 | 毫秒级 | 秒级 | 秒~分级 |
| 捕获 DELETE | 支持 | 支持 | 不支持 |
| 性能影响 | 几乎无 | 明显 | 取决于轮询频率 |
| 维护复杂度 | 中 | 高 | 低 |
| 适用场景 | 生产核心、高并发 | 低并发、小表 | 数据量小、可接受延迟 |
下面这张图,是我自己画的一个 CDC 整体架构图,帮你把三种方式的关系理清楚:
数据一致性面临的挑战
CDC 听起来很美好,但真正用起来,你会发现到处都是坑。数据一致性是 CDC 最核心的难题,我总结下来主要有三个「拦路虎」。
1. 延迟(Latency)
从源库数据变更,到目标库看到这条数据,中间有时间差。这个差就是延迟。
- 原因:日志传输、网络抖动、目标库写入压力、CDC 工具自身处理瓶颈。
- 后果:用户读到旧数据;报表统计口径不一致;下游依赖实时数据的业务逻辑出错。
我的做法:监控端到端延迟是 CDC 运维的必修课。我习惯在每条变更记录里嵌入一个「变更时间戳」,目标端收到后跟当前时间做差,超过阈值就告警。
2. 乱序(Out-of-Order)
同一个主键的数据,先发生的变更可能后到达目标端。比如用户先 UPDATE 了手机号,又 UPDATE 了地址,但目标端可能先收到地址变更,再收到手机号变更。
- 原因:多线程并行消费、网络传输路径不同、源库日志分片。
- 后果:目标端数据状态与源端不一致,出现「数据回滚」的假象。
避坑指南:我曾经遇到过一个案例,因为乱序导致下游数仓里用户的「最后登录时间」比「注册时间」还早。排查了两天才发现是 CDC 消费线程乱序导致的。后来我强制按主键哈希分区,保证同一个主键的变更进入同一个消费线程。
3. 重复(Duplication)
同一条变更记录被 CDC 工具发送了多次,目标端重复消费。
- 原因:CDC 工具重启后重新读取未确认的偏移量;网络重试机制;源库日志归档后重新读取。
- 后果:目标端数据重复;下游聚合计算(如 SUM、COUNT)结果翻倍。
这三种挑战,我整理了一个速查表,方便你对照排查:
| 挑战 | 典型表现 | 常见原因 | 初步应对思路 |
|---|---|---|---|
| 延迟 | 目标端数据落后源端 | 消费能力不足、网络瓶颈 | 增加并行度、优化写入 |
| 乱序 | 数据状态异常回滚 | 多线程无序消费 | 按主键分区、使用序列号 |
| 重复 | 数据量异常增长 | 重启重试、偏移量未提交 | 目标端去重、幂等写入 |
好了,这一章的基础概念就聊到这儿。CDC 不是银弹,它有自己的脾气和局限。理解了这些挑战,后面我们讲数据校验和异常恢复方案时,你才能知道每个方案到底在解决什么问题。