1. CDC 概念与原理

各位同学好,我是老张。今天咱们正式开讲《CDC 实现埋点数据实时同步》的第一章。说实话,做了这么多年数据工程,CDC 这个概念我几乎每天都在用。但真要把它讲清楚,还得从最基础的东西说起。

1.1 什么是 CDC

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

你想想看,传统的数据同步方式,通常是半夜跑个批处理,把全量数据导一遍。但 CDC 不一样——它只关注「变化」:哪条记录被插入了、哪条被更新了、哪条被删除了。然后把这些变化实时推给下游系统。

我记得 2018 年刚接触 CDC 时,有个同事问我:「这不就是数据库的触发器吗?」嗯,有点像,但 CDC 的定位完全不同。它更像一个「数据变化的监听器」,而且对源库几乎无侵入。

核心定义:CDC 是一种通过捕获数据库事务日志或数据变更事件,实现增量数据实时同步的技术方案。

1.2 CDC 在数据同步中的角色

在数据同步这个领域,CDC 扮演的角色非常明确——它负责「增量实时同步」。我习惯把数据同步分成三层来看:

  • 采集层:从源端获取数据变化事件
  • 传输层:把事件可靠地送到目标端
  • 应用层:在目标端还原数据变更

CDC 主要工作在采集层和应用层。它不负责全量数据的搬运,只关心「增量」。我在做埋点数据同步时,经常把 CDC 比作「数据管道的水龙头」——它控制着数据流的开关和流速。

我的经验:在埋点场景下,CDC 最适合处理用户行为日志这类高频、小数据量的变更。如果是几十亿条的大表全量同步,还是得靠批处理。

1.3 CDC 与批量同步的区别

很多新手容易把 CDC 和批量同步搞混。我直接画个表格,你一看就明白:

对比维度 CDC 实时同步 批量同步(ETL)
同步频率 秒级/毫秒级 小时级/天级
数据量 仅增量变化 全量或大范围
延迟 亚秒级 分钟级起步
对源库影响 极低(读日志) 较高(全表扫描)
适用场景 实时报表、埋点、监控 数据仓库、离线分析
实现复杂度 中等 较低

为什么 CDC 对源库影响低?因为它不直接查询业务表,而是读取数据库的事务日志。我曾经在线上环境做过对比:同样同步 100 万条变更数据,CDC 方式对源库的 CPU 消耗不到批量方式的 5%。

避坑指南:我曾经遇到一个项目,团队用 CDC 去同步一张每天全量更新的配置表。结果 CDC 捕获了 100% 的变更,但实际只有 1% 是有效数据。记住:CDC 适合「增量变化频繁但单次变化量小」的场景。

1.4 CDC 的常见实现方式

CDC 的实现方式主要有三种。我按推荐程度排个序:

1.4.1 基于日志(最推荐)

这是目前最主流的方式。原理很简单:数据库在写入数据时,会先写事务日志(比如 MySQL 的 binlog、PostgreSQL 的 WAL)。CDC 工具直接解析这些日志,就能拿到所有变更。

我为什么最推荐这种方式?因为它对源库完全无侵入。你不需要改表结构,不需要加触发器,甚至不需要额外的权限。我在做埋点数据同步时,90% 的场景都用这种方式。

-- MySQL binlog 示例(伪代码)
-- 开启 binlog
SET GLOBAL binlog_format = 'ROW';
-- 查看当前 binlog 位置
SHOW MASTER STATUS;
-- 解析 binlog 中的插入事件
-- binlog 内容:INSERT INTO user_click (uid, page, ts) VALUES (123, 'home', '2024-01-01 10:00:00')

优点:无侵入、实时性高、支持所有 DML 操作(INSERT/UPDATE/DELETE)

缺点:需要数据库开启日志功能,解析日志有一定技术门槛

1.4.2 基于触发器

这种方式是在源表上创建触发器,当数据发生变化时,触发器把变更记录写入一张专门的「变更表」。CDC 工具再读取这张变更表。

说实话,我不太推荐这种方式。为什么?因为触发器本身对数据库性能有影响。我曾经在一个高并发系统上试过,加了触发器后,写入性能直接下降了 30%。

-- 触发器示例(MySQL)
CREATE TRIGGER trg_user_click_cdc
AFTER INSERT ON user_click
FOR EACH ROW
BEGIN
    INSERT INTO cdc_changes (table_name, operation, data, change_time)
    VALUES ('user_click', 'INSERT', JSON_OBJECT('uid', NEW.uid, 'page', NEW.page), NOW());
END;

避坑指南:我曾经在一个金融项目中,因为触发器导致主库写入延迟飙升。后来排查发现,触发器里做了 JSON 序列化,每次插入都多消耗 5ms。记住:触发器方式只适合低并发、对实时性要求不高的场景。

1.4.3 基于时间戳

这种方式需要在源表上加一个「最后修改时间」字段。CDC 工具定期查询这个字段,找出时间戳大于上次同步时间的记录。

嗯,这种方式最简单,但问题也最多。首先,它无法捕获 DELETE 操作(除非用软删除)。其次,如果系统时间不准,或者有批量更新,很容易漏数据。

-- 基于时间戳的增量查询示例
SELECT * FROM user_click
WHERE update_time > '2024-01-01 10:00:00'
  AND update_time <= '2024-01-01 10:05:00';

我的建议:如果业务允许秒级延迟,且数据量不大,时间戳方式可以作为临时方案。但长期来看,还是得切换到基于日志的方式。

1.5 三种实现方式对比

我把三种方式的核心差异整理成一张表,方便你对比:

实现方式 实时性 对源库影响 支持 DELETE 实现难度 推荐场景
基于日志 毫秒级 极低 是 中等 埋点、实时数仓、监控
基于触发器 毫秒级 较高 是 低 低并发、简单场景
基于时间戳 秒级 低 否 极低 临时方案、非关键数据

1.6 CDC 核心流程示意图

下面这张图展示了 CDC 从数据捕获到目标端应用的完整流程。我特意把三种实现方式都画进去了:

CDC 核心流程示意图 源数据库 基于日志 (binlog/WAL) 基于触发器 基于时间戳 CDC 数据流处理 目标系统 说明 • 日志方式:无侵入,推荐 • 触发器:有性能影响 • 时间戳:不支持 DELETE

从这张图你能看到,无论用哪种捕获方式,最终都会汇聚到 CDC 数据流处理层。这一层负责数据格式转换、过滤、去重,然后推送到目标系统。

1.7 小结

这一章我们讲了 CDC 的核心概念和三种实现方式。我个人觉得,理解 CDC 的关键就一句话:它只关心「变化」,不关心「全量」。

在埋点数据实时同步这个场景里,CDC 的优势非常明显——用户行为数据变化快、单条数据小、对实时性要求高。用基于日志的 CDC 方式,几乎是最优解。

嗯,第一章就到这里。内容不多,但都是基础中的基础。后面我们会一步步深入,从环境搭建到实战案例,把 CDC 在埋点同步中的应用彻底讲透。