1. Debezium 概述与架构:CDC 概念、核心组件与 Kafka Connect 集成

1.1 什么是 CDC?为什么我们需要它?

CDC,全称是 Change Data Capture,中文叫「变更数据捕获」。说白了,就是实时监听数据库里的数据变化——谁插入了新记录、谁更新了字段、谁删了一行数据,都能被捕获到。

我刚开始接触这个领域时,很多团队还在用轮询的方式去查数据库。比如每隔几秒跑一个 SELECT * FROM orders WHERE update_time > ?。这种做法在小规模还行,一旦数据量上来,数据库压力大得吓人。而且你想想看,轮询间隔再短也有延迟,永远做不到真正的实时。

CDC 的核心思路是:让数据库自己把变更「推」出来。常见实现方式有两种:

  • 基于日志的 CDC:直接读取数据库的事务日志(比如 MySQL 的 binlog、PostgreSQL 的 WAL)。性能最好,对业务库几乎零侵入。
  • 基于触发器的 CDC:在表上建触发器,把变更记录到另一张表。侵入性强,性能损耗大,我一般不建议在生产环境用。

核心要点:Debezium 采用的是「基于日志的 CDC」方案。它把自己伪装成一个 MySQL Slave 或 PostgreSQL Standby,直接从日志流里读取变更事件。这种方式延迟通常在毫秒级,而且不会给源库增加额外查询压力。

1.2 Debezium 的核心组件

Debezium 不是一个单体服务,它由几个关键模块组成。我习惯把它们分成三层来看:

组件 角色 我的理解
Connector 连接器,负责对接具体数据库 每个数据库类型对应一个 Connector,比如 MySQL Connector、PostgreSQL Connector
Snapshotter 快照器,负责初始数据全量同步 第一次启动时,先把表里已有的数据全部读出来,再切到增量监听
Offset Storage 偏移量存储,记录消费位置 记录 binlog 文件名和位置,重启后从断点续传,不会丢数据
Event Converter 事件转换器,把数据库变更转成统一格式 把 binlog 事件转成 Debezium 的 Change Event 结构,包含 before/after 字段

嗯,这里要注意:Offset 的存储位置非常关键。我曾经遇到过一个事故,Kafka Connect 的 offset 存储在本地文件系统,结果容器被重新调度后 offset 丢了,导致重复消费了上百万条数据。所以生产环境我强烈建议把 offset 存到 Kafka 内部 topic 里。

1.3 Kafka Connect 集成:Debezium 的运行底座

Debezium 本身不是一个独立运行的服务。它是以 Kafka Connect 插件的形式存在的。Kafka Connect 是 Kafka 生态里的一个框架,专门用来做数据导入导出。

你可以把 Kafka Connect 理解成一个「插槽板」,Debezium 就是插在上面的一块功能卡。Kafka Connect 负责管理 Debezium 的生命周期——启动、停止、重启、扩缩容。

Kafka Connect 有两种运行模式:

  • Standalone 模式:单进程运行,适合开发和测试。配置简单,但挂了就全挂了。
  • Distributed 模式:多节点集群,支持高可用和自动故障转移。生产环境必须用这个。

我的建议:即使你只有一台机器,也请用 Distributed 模式启动。因为未来扩节点时,不需要改任何配置,直接把新节点加入集群就行。我在项目里吃过 Standalone 模式的亏——业务量翻倍后,单节点扛不住,迁移到 Distributed 模式时还得重新规划 offset 存储。

一个典型的 Debezium + Kafka Connect 部署架构是这样的:

MySQL (binlog) 
    ↓ 模拟 Slave 协议读取
Debezium MySQL Connector (运行在 Kafka Connect 中)
    ↓ 输出 Change Event
Kafka Topic (例如:dbserver1.inventory.customers)
    ↓ 下游消费
Flink / Spark / 数据同步服务 / 缓存更新

每个 Debezium Connector 在启动时,会向 Kafka Connect 注册一个任务。这个任务会持续不断地读取 binlog,把变更事件写入到指定的 Kafka Topic 中。Topic 的命名规则通常是 serverName.schemaName.tableName。

1.4 应用场景分析:Debezium 能解决什么问题?

我参与过的项目中,Debezium 最常见的几个应用场景:

  1. 缓存失效与更新:数据库里的数据变了,自动通知 Redis 或 CDN 清除缓存。我以前做过一个电商项目,商品信息变更后,通过 Debezium 触发缓存更新,延迟控制在 200ms 以内。
  2. 异构数据同步:从 MySQL 同步到 Elasticsearch,或者从 PostgreSQL 同步到 ClickHouse。不用写 ETL 脚本,Debezium 自动搞定。
  3. 微服务事件驱动:订单服务创建订单后,通过 Debezium 把订单事件发到 Kafka,下游的库存服务、物流服务各自消费。这样订单服务不需要知道下游有哪些服务。
  4. 审计日志:记录所有数据变更的 before/after 状态,满足合规要求。我遇到过金融客户,监管要求必须保留 3 年的数据变更历史,Debezium 配合 Kafka 的日志保留策略完美解决。
  5. 实时数仓:把业务库的变更实时同步到数仓,替代传统的 T+1 批量同步。

避坑指南:我曾经在一个项目中,把 Debezium 直接用于跨机房的数据同步。结果发现网络延迟导致 binlog 读取超时,Connector 频繁重启。后来加了专线和调整了 connect.timeout.ms 参数才稳定下来。所以,Debezium 对源库的网络稳定性要求很高,跨机房部署一定要做好网络监控。

1.5 整体架构图:一张图看懂 Debezium 的工作流程

下面这张图是我自己总结的 Debezium 核心架构。它把上面讲到的组件串联起来了:

Debezium 核心架构与数据流 源数据库 MySQL / PostgreSQL / MongoDB 事务日志 (binlog/WAL) Debezium Connector Snapshotter + Event Converter Kafka Connect Runtime Offset Storage Kafka Topic 下游消费者 说明: 1. Connector 读取事务日志 2. 转换为 Change Event 3. 写入 Kafka Topic

从这张图可以看得很清楚:数据从源数据库的事务日志流出,经过 Debezium Connector 的转换,最终进入 Kafka Topic。Offset Storage 负责记录消费位置,保证数据不丢不重。下游的消费者可以是任何订阅了 Kafka Topic 的服务。

1.6 小结:Debezium 到底好在哪?

做了这么多年数据架构,我见过太多 CDC 方案了。有的基于触发器,有的基于应用层双写,有的用 Canal 或 Maxwell。但 Debezium 有几个让我坚持用它的理由:

  • 生态好:原生集成 Kafka Connect,上下游生态非常成熟。
  • 数据库覆盖广:MySQL、PostgreSQL、MongoDB、Oracle、SQL Server 都支持。
  • 社区活跃:Red Hat 在背后维护,版本迭代快,遇到问题基本都能在 GitHub Issues 里找到答案。
  • 配置灵活:可以按表、按库过滤,可以自定义事件格式,可以控制快照行为。

当然,它也不是银弹。比如对源库的 binlog 格式有要求(MySQL 必须用 ROW 模式),比如 Kafka 集群本身需要维护成本。但总体来说,在 CDC 这个领域,Debezium 是目前最成熟的开源方案之一。