增量迁移的基石:什么是CDC?
聊增量迁移,绕不开一个核心概念——CDC。
CDC,全称 Change Data Capture,中文叫「变更数据捕获」。说白了,就是实时捕捉数据库里的数据变化。插入、更新、删除,每一条操作都能被捕获到。
我刚开始接触这个术语时,觉得它挺玄乎。后来做了一次全量重跑,几十亿数据跑了整整两天,业务方差点没把我电话打爆。嗯,从那以后,我彻底理解了CDC的价值。
CDC的核心作用就一个:让下游系统只处理变化的数据,而不是全量数据。你想想看,如果每次同步都全量拉一遍,数据量小还行,上了TB级别,谁也扛不住。
CDC的本质:把数据库的增量变更,变成一条条可消费的事件流。
CDC的三种常见实现方式
实现CDC的方式有好几种,但真正在生产环境里常用的,就三种。我按推荐程度排个序,咱们一个一个说。
1. 基于日志的CDC
这是我最推荐的方式,也是目前大厂的主流选择。
原理很简单:数据库本身就有事务日志(比如MySQL的binlog、PostgreSQL的WAL、Oracle的Redo Log)。这些日志记录了每一次数据变更的完整信息。CDC工具直接读取这些日志,解析出变更事件,然后推送给下游。
为什么我偏爱这种方式?因为它对业务代码零侵入。不需要改表结构,不需要加触发器,不需要改应用程序。数据库该怎么跑还怎么跑,CDC工具在背后默默干活。
我的经验:在MySQL场景下,我习惯用Canal或Debezium来消费binlog。Debezium配合Kafka,基本是业界标准方案。记得把binlog格式设为ROW模式,否则你拿到的可能是模糊的SQL语句,而不是精确的变更数据。
基于日志的CDC有几个明显优势:
- 实时性高:日志一写,CDC立马就能读到,延迟通常在毫秒级
- 不丢数据:日志是数据库持久化的一部分,只要日志在,数据就不会丢
- 性能影响小:读取日志是文件级别的操作,对数据库本身几乎无压力
当然,它也有缺点。比如,需要额外的组件来解析日志,运维成本稍高。另外,如果数据库版本升级,日志格式可能变化,CDC工具也得跟着适配。
2. 基于触发器的CDC
这种方式,说白了就是在表上建触发器。每次有数据变更,触发器就把变更记录写到一张专门的变更表里。CDC工具再去读这张变更表。
我在早期项目中用过这种方式。当时数据库不支持binlog,没办法,只能上触发器。
我曾经踩过的坑:触发器方式最大的问题是性能。有一次我在一张高频写入的表上加了触发器,结果数据库的写入性能直接掉了30%。触发器是在事务内执行的,它会拖慢每一次DML操作。如果你的表写入量很大,慎用。
基于触发器的CDC优缺点很明显:
| 优点 | 缺点 |
|---|---|
| 实现简单,不依赖外部组件 | 对数据库性能有明显影响 |
| 兼容性好,几乎所有数据库都支持触发器 | 需要额外维护变更表,增加存储开销 |
| 可以自定义捕获逻辑 | 触发器本身也是代码,有维护成本 |
| 如果触发器逻辑出错,可能影响主库写入 |
我个人建议,除非实在没办法,否则尽量别用触发器做CDC。它更适合那种数据量不大、对实时性要求不高的场景。
3. 基于时间戳的CDC
这种方式最「朴素」。在表里加一个时间戳字段(比如 update_time),每次更新数据时更新这个字段。CDC工具定期扫描这张表,根据时间戳筛选出最近变更的数据。
你可能会问:「这也能叫CDC?」嗯,严格来说它确实算一种增量捕获方式,只是比较粗糙。
适用场景:数据量小(百万级以下)、对实时性要求不高(分钟级或小时级)、没有复杂删除操作的场景。
我在一个内部管理系统里用过这种方式。数据量不大,每天变更也就几千条,用时间戳完全够用。但如果你要处理的是核心交易数据,千万别这么干。
基于时间戳的CDC有几个硬伤:
- 无法捕获删除操作:删掉的数据,时间戳也没了,你根本不知道它被删过
- 时间精度问题:如果同一秒内有多条数据变更,可能漏掉一部分
- 扫描压力大:每次都要全表扫描或索引扫描,数据量大了根本扛不住
- 延迟较高:扫描周期决定了延迟,做不到秒级
下面这张图,我把三种方式的对比画了出来,方便你直观理解:
三种方式怎么选?
说实话,没有银弹。选哪种,取决于你的场景。
我个人习惯是这样的:
- 新项目:直接上基于日志的CDC。Debezium + Kafka 是标配,MySQL用Canal也行。别犹豫,这是最省心的路。
- 老系统改造:如果数据库不支持日志解析,或者DBA不让开binlog,那就用触发器。但一定要做好性能压测,别上线了才发现扛不住。
- 临时方案或小项目:时间戳方式可以快速上线。但记住,这只是过渡方案,别想着一直用下去。
我的建议:如果你刚开始做增量迁移,优先考虑基于日志的CDC。虽然前期搭建成本高一点,但后期运维省心太多。我曾经在一个项目里先用时间戳凑合,结果数据对不上,排查了三天才发现是时间戳精度问题。后来换成binlog,再也没出过类似问题。
好了,CDC的概念和三种实现方式就聊到这儿。记住一句话:CDC是增量迁移的基石,选对方式,后面的事就顺了。