2. CDC技术选型
聊到 CDC,很多人第一反应就是「哦,监听 binlog 嘛」。但说实话,我在实际项目中踩过的坑告诉我——选型这事,真没那么简单。
今天咱们就把三种主流 CDC 方案掰开揉碎讲清楚:基于日志的 CDC、基于触发器的 CDC、基于时间戳的 CDC。每种方案我都会结合自己的实战经验,告诉你什么时候该用,什么时候千万别碰。
一句话总结:没有银弹。日志型 CDC 是当前主流,但触发器和时间戳在某些场景下反而更香。
一、基于日志的 CDC:当前的主流选择
说白了,就是让工具去读数据库的 binlog(MySQL)或 WAL(PostgreSQL),然后解析成变更事件。Debezium、Canal、Maxwell 都是干这个的。
优点很明显:
- 对源库零侵入——不需要改表结构,不需要加触发器,DBA 看了都开心
- 实时性极高——毫秒级延迟,binlog 一写入就能捕获
- 捕获完整变更——INSERT、UPDATE、DELETE 全都能抓到,包括旧值和新值
- 支持 Exactly-Once 语义——配合 Kafka,能做到不丢不重
缺点也得说清楚:
- 运维成本不低——Debezium 要搭 Kafka Connect 集群,Canal 要维护 ZooKeeper
- 对数据库有额外压力——binlog 的读取会增加磁盘 IO,高并发场景下要注意
- DDL 变更处理麻烦——表结构改了,同步任务可能挂掉,我遇到过好几次
- 不是所有数据库都支持——比如 SQLite、老版本 MySQL 就不行
我的经验:我个人习惯用 Debezium + Kafka 的组合。有一次帮客户做 MySQL 到 Hudi 的实时同步,每天几亿条数据,Debezium 扛了半年没出过问题。但要注意——binlog 格式必须设为 ROW,不然你会后悔的。
二、基于触发器的 CDC:老派但可靠
这个方案很直接——在源表上建触发器,每次 INSERT/UPDATE/DELETE 就把变更记录写到一张专门的日志表里。然后另起一个进程去读这张日志表。
优点:
- 数据库无关性——只要支持触发器就能用,Oracle、SQL Server、MySQL 都行
- 实现简单——几条 SQL 就能搞定,不需要额外组件
- 能捕获所有变更——包括 DELETE 操作(时间戳方案做不到)
缺点也很致命:
- 对源库性能影响大——每次 DML 都要多写一次日志表,高并发下触发器会成为瓶颈
- 维护成本高——表结构变了,触发器也得跟着改
- 容易造成死锁——我在项目中遇到过,触发器里的事务没处理好,直接把业务库拖垮了
- 日志表会膨胀——不清理的话,几个月就能撑爆磁盘
避坑指南:我曾经在一个金融项目中被迫使用触发器 CDC,因为客户的 Oracle 数据库是第三方托管的,不给开归档日志。结果上线第一天,触发器在高并发下产生了死锁,业务直接停了 20 分钟。后来我们加了异步队列才解决。所以——能用日志型就别用触发器,除非你真的没得选。
三、基于时间戳的 CDC:简单但有限
这个方案最朴素——在表里加一个 last_modified 字段,每次更新时更新这个时间戳。同步程序定期查询 WHERE last_modified > 上次同步时间。
优点:
- 实现最简单——一条 SQL 搞定,不需要任何额外组件
- 对数据库几乎无影响——就是普通的 SELECT 查询
- 适合离线批量同步——比如每天凌晨跑一次全量同步
缺点:
- 无法捕获 DELETE——删掉的数据就没了,除非用软删除
- 实时性差——取决于轮询间隔,分钟级到小时级
- 时间精度问题——如果同一秒内有多条更新,可能会漏数据
- 不支持历史变更追溯——只能拿到最新状态,看不到中间变化
我的用法:时间戳 CDC 我一般只用来做兜底校验。比如用 Debezium 做主同步,每天凌晨再用时间戳方式跑一次全量对比,把漏掉的数据补回来。说白了,它适合做「保底方案」,不适合做主力。
四、三种方案对比表
| 对比维度 | 基于日志的 CDC | 基于触发器的 CDC | 基于时间戳的 CDC |
|---|---|---|---|
| 实时性 | 毫秒级 | 毫秒级 | 分钟/小时级 |
| 源库侵入性 | 低(读日志) | 高(加触发器) | 低(加字段) |
| 捕获 DELETE | ✅ 支持 | ✅ 支持 | ❌ 不支持 |
| 历史变更追溯 | ✅ 完整 | ✅ 完整 | ❌ 仅最新 |
| 运维复杂度 | 高(需维护组件) | 中(需管理触发器) | 低(简单 SQL) |
| 数据库兼容性 | 有限(需 binlog/WAL) | 广泛(支持触发器的都行) | 广泛(有字段就行) |
| 典型工具 | Debezium, Canal, Maxwell | 自建触发器 + 日志表 | 自建轮询脚本 |
五、选型建议:我给你的决策树
你想想看,选 CDC 方案其实就三个问题:
- 你的数据库支持 binlog/WAL 吗?
- 支持 → 优先选日志型 CDC(Debezium 或 Canal)
- 不支持 → 看第二个问题
- 你能接受对源库做改造吗?
- 能接受 → 触发器 CDC(但要评估性能影响)
- 不能接受 → 看第三个问题
- 你的实时性要求有多高?
- 分钟级可以接受 → 时间戳 CDC(最简单)
- 需要秒级实时 → 考虑用其他方案或混合使用
我的推荐组合:
- 主力同步:Debezium + Kafka(日志型 CDC)
- 兜底校验:每天凌晨时间戳 CDC 跑一次全量对比
- 异常处理:触发器 CDC 作为最后的备选方案
这个组合我在三个生产项目中验证过,稳得很。
嗯,CDC 选型就聊到这儿。记住一句话:没有最好的方案,只有最适合你场景的方案。日志型 CDC 是当前的主流,但别盲目跟风——如果你的数据库不支持 binlog,或者你的团队没有运维 Kafka 的能力,那触发器或时间戳反而是更务实的选择。