1. Debezium 初探:什么是 CDC?Debezium 的诞生背景与核心价值

1.1 从一个真实问题说起

先讲个我亲身经历的事。

几年前我在一家电商公司做架构升级。订单系统每天产生几百万条数据,这些数据要同步到搜索引擎、缓存、数据仓库和推荐系统。传统做法是写定时任务,每五分钟跑一次批量同步。

问题来了。

凌晨大促期间,订单状态变化极快。五分钟的延迟,意味着用户付了款,搜索结果还显示「待支付」。客服电话被打爆,运营同学急得跳脚。更糟的是,批量同步经常把数据库 CPU 打满,影响正常交易。

我当时就在想:能不能让数据一发生变化,就立刻通知下游?

这就是 CDC 要解决的核心问题。

1.2 什么是 CDC?

CDC 全称是 Change Data Capture,中文叫「变更数据捕获」。说白了,就是实时监听数据库里的数据变化——新增、修改、删除——然后把这些变化事件推送给其他系统。

你想想看,传统同步方式是什么?

  • 定时批量拉取:每隔几分钟跑一次 SQL,查「更新时间 > 上次拉取时间」的数据。延迟高,对数据库有压力。
  • 双写:业务代码里同时写数据库和缓存/搜索引擎。侵入性强,容易造成数据不一致。

CDC 的思路完全不同。它不依赖业务代码,也不依赖定时任务。它直接从数据库的事务日志里读取变更记录,然后以事件流的形式推出去。

核心要点:CDC 是一种基于日志的、非侵入式的数据同步方案。它把数据库变成了一个事件源。

常见的 CDC 实现方式有三种:

实现方式 原理 典型代表 优缺点
基于日志 读取数据库事务日志(如 MySQL binlog、PostgreSQL WAL) Debezium、Canal、Maxwell 低延迟、无侵入、支持全量+增量
基于触发器 在数据库表上创建触发器,捕获变更写入日志表 自建方案 对数据库性能影响大,维护成本高
基于时间戳 查询表中「更新时间」字段,增量拉取 自建方案 延迟高,需要业务表有更新时间字段

我个人习惯把 CDC 理解为「数据库的流式接口」。它让数据库不再只是一个存储容器,而是变成了一个持续产生事件的数据源。

1.3 Debezium 的诞生背景

CDC 的概念并不新。早在 2010 年左右,LinkedIn 的 Databus、Oracle 的 GoldenGate 就已经在做类似的事。但问题是,这些工具要么是商业软件,要么与特定技术栈深度绑定。

2016 年,Red Hat 开源了 Debezium。它的目标很明确:

  • 让 CDC 变得简单:开发者不需要理解底层日志格式,只需要配置一个连接器。
  • 与 Kafka 深度集成:Debezium 基于 Kafka Connect 框架构建,天然支持高吞吐、持久化和多消费者。
  • 支持多种数据库:MySQL、PostgreSQL、MongoDB、Oracle、SQL Server……一个框架搞定。

我记得 Debezium 刚出来那会儿,社区里还有人质疑:「Kafka Connect 本身就有学习成本,再加一层 Debezium,值得吗?」

后来大家发现,Debezium 真正解决了几个痛点:

  1. 日志解析的复杂性:MySQL binlog 的格式、PostgreSQL WAL 的 decoding 插件、MongoDB oplog 的结构……每个数据库都不一样。Debezium 把这些差异封装好了。
  2. 断点续传:记录消费位点,系统重启后可以从上次中断的地方继续读取,不会丢数据。
  3. Schema 演化:数据库表结构变了,Debezium 会自动感知并更新事件的结构。

一个小提示:如果你刚开始接触 Debezium,建议先从 MySQL 或 PostgreSQL 入手。这两个数据库的社区文档最全,踩坑也最少。

1.4 Debezium 的核心价值

说了这么多,Debezium 到底能帮我们解决什么问题?我总结了几点:

1.4.1 实时数据同步

这是最直接的应用。订单数据变更后,毫秒级同步到 Elasticsearch、Redis、缓存层。用户搜到的结果永远是「热乎」的。

1.4.2 微服务间的数据一致性

微服务架构下,每个服务有自己的数据库。订单服务的数据变了,库存服务、支付服务、通知服务怎么知道?

传统做法是发消息队列通知。但消息可能丢失,可能重复,可能顺序错乱。Debezium 提供了一种「基于数据库日志」的可靠通知机制——数据变了,事件一定发出。

1.4.3 数据湖与流式入仓

很多公司把 MySQL 数据实时同步到 Hudi、Iceberg 或 Delta Lake。Debezium 配合 Kafka,可以做到秒级入湖,而且保证 Exactly-Once 语义。

1.4.4 审计与溯源

Debezium 捕获的每条变更事件都包含「之前的值」和「之后的值」。谁改了数据?改了什么?什么时候改的?一目了然。这在金融、合规场景下非常有用。

注意:Debezium 不是银弹。它依赖 Kafka,意味着你的团队需要具备 Kafka 运维能力。另外,对于低频变更的场景,引入 Debezium 可能有点「杀鸡用牛刀」。

1.5 Debezium 的整体架构

下面这张图展示了 Debezium 在数据流中的位置。我建议你先看个大概,后续章节会逐一拆解每个组件。

Debezium 整体架构图 Debezium 整体架构 MySQL PostgreSQL MongoDB 数据源层 Debezium Connector 读取 binlog / WAL / oplog → 解析为结构化事件 Debezium 连接器层 Apache Kafka Topic: dbserver1.inventory.customers 消息中间件层 Elasticsearch 数据湖 / 数仓 微服务 / 缓存 下游消费层 Debezium 作为 Kafka Connect 的 Source Connector,将数据库变更事件实时推入 Kafka Topic

这张图里,Debezium 扮演的角色很清晰:它坐在数据库和 Kafka 之间,负责把数据库的变更日志「翻译」成 Kafka 能理解的事件。

嗯,这里要注意一点:Debezium 本身不存储数据,它只是一个连接器。数据最终落在 Kafka 里,由下游消费者自行处理。

1.6 一个简单的例子

假设 MySQL 里有一张 customers 表:

CREATE TABLE customers (
  id INT PRIMARY KEY,
  name VARCHAR(100),
  email VARCHAR(100)
);

当执行一条 UPDATE 语句:

UPDATE customers SET email = 'new@example.com' WHERE id = 1;

Debezium 会捕获这条变更,并向 Kafka 发送一条类似下面的事件(简化版):

{
  "op": "u",           // 操作类型:c=create, u=update, d=delete
  "before": {          // 变更前的值
    "id": 1,
    "name": "张三",
    "email": "old@example.com"
  },
  "after": {           // 变更后的值
    "id": 1,
    "name": "张三",
    "email": "new@example.com"
  },
  "source": {          // 元数据
    "db": "mydb",
    "table": "customers",
    "ts_ms": 1700000000000
  }
}

你看,这个事件包含了完整的前后对比。下游系统拿到后,可以直接更新 Elasticsearch 文档,或者触发缓存失效,或者写入审计日志。

避坑指南:我曾经遇到一个坑——Debezium 默认会为每个表生成一个独立的 Kafka Topic。如果表数量很多(比如上千张),Topic 数量会爆炸。建议提前规划 Topic 的命名规则和分区策略。

1.7 什么时候该用 Debezium?

不是所有场景都需要 CDC,更不是所有场景都需要 Debezium。我列了几个判断标准:

  • 延迟要求高:秒级甚至毫秒级同步,批处理做不到。
  • 数据一致性要求高:不能丢数据,不能重复消费。
  • 不想改业务代码:CDC 是非侵入式的,不需要在业务逻辑里加同步代码。
  • 已经用了 Kafka:如果团队已经有 Kafka 基础设施,Debezium 的接入成本很低。

反过来,如果你的数据量很小,或者对实时性没要求,或者团队没有 Kafka 运维能力,那用定时任务或者 binlog 监听脚本可能更简单。