3. Debezium 深度解析:架构、核心组件与部署模式

Debezium 这个项目,说白了就是 CDC 领域的瑞士军刀。我最早接触它是在 2018 年,当时要做一个 MySQL 到 Kafka 的实时同步,对比了几款工具后,发现 Debezium 对 binlog 的解析最干净,而且社区活跃度很高。这么多年用下来,它已经成了我搭建实时数据管道时的首选。

这一章,咱们就把它拆开揉碎了看。从整体架构到核心组件,再到几种部署方式,我会把我在项目中踩过的坑和积累的经验都抖出来。

3.1 Debezium 整体架构

先看一张架构图,帮你建立整体认知。

Debezium 整体架构图 Debezium 整体架构 MySQL / PostgreSQL 源数据库 Debezium 核心 Connector + Snapshot + Streaming (Kafka Connect Worker) Kafka Topic 变更事件流 核心组件内部 Snapshot 阶段 初始全量数据读取 Streaming 阶段 持续增量变更捕获 Offset 管理 断点续传 / 故障恢复 部署模式 单机模式 (Standalone) 分布式模式 (Distributed) 嵌入式模式 (Embedded) 说明:Debezium 基于 Kafka Connect 框架运行,Connector 是核心插件,Snapshot 和 Streaming 是其内部两个关键阶段

这张图把 Debezium 的脉络理清楚了。数据从源库流出,经过 Debezium 的加工,最终进入 Kafka。你想想看,整个过程就像一条流水线——源数据库是原料仓库,Kafka 是成品货架,而 Debezium 就是中间那条传送带和加工车间。

3.2 核心组件详解

3.2.1 Connector —— 连接器的灵魂

Connector 是 Debezium 的入口。每个 Connector 对应一个数据源,比如 MySQLConnector、PostgresConnector、MongoDbConnector。它的职责很简单:告诉 Kafka Connect 框架「我要从哪里读数据,怎么读,读到后怎么处理」。

我个人习惯把 Connector 的配置拆成三块来看:

  • 连接配置:数据库地址、端口、用户名、密码。嗯,这里要注意,密码千万别写死在配置文件里,用环境变量或者 Secret Manager 来管理。
  • 表过滤配置:table.include.list 和 table.exclude.list。我曾经在项目里忘了配这个,结果把系统库的几百张表全同步过来了,Kafka 里瞬间多了上千个 Topic,运维同学差点没把我拉黑。
  • 行为配置:快照模式、偏移量提交频率、事件格式等。

核心要点:Connector 本身不处理数据,它只是「监工」。真正干活的是它内部启动的 Task。一个 Connector 可以启动多个 Task 来并行读取,但要注意源库的连接数限制。

3.2.2 Snapshot —— 全量数据的「快照」

当 Connector 第一次启动时,它需要先拿到数据库的当前全量数据。这个过程就叫 Snapshot。为什么要有这一步?因为 CDC 只能捕获变更,如果连初始状态都没有,后面的变更就无从谈起。

Debezium 提供了几种快照模式:

模式 说明 适用场景
initial 先做全量快照,再切换到流式读取 默认模式,大多数场景的首选
when_needed 仅在需要时触发快照(如偏移量丢失) 已有数据,只需增量同步
never 跳过快照,直接开始流式读取 只关心增量数据,不关心历史
schema_only 只捕获表结构,不读取数据行 只需要 Schema 变更的场景

我记得有一次做迁移,源库有 2TB 的数据,用默认的 initial 模式跑了整整 6 个小时。后来我改成 snapshot.mode=when_needed,配合手动触发快照,把大表拆成多个小批次,才把时间降下来。说白了,快照不是小事,大表一定要提前规划。

避坑指南:快照期间,Debezium 会持有数据库的读锁(取决于隔离级别和数据库类型)。我曾经在生产环境上跑快照,结果导致业务查询被阻塞了十几秒。后来我学乖了——快照尽量放在业务低峰期,或者使用 snapshot.locking.mode=none 配合一致性快照。

3.2.3 Streaming —— 持续不断的「流」

快照完成后,Debezium 会自动切换到 Streaming 模式。它会持续监听数据库的变更日志(比如 MySQL 的 binlog、PostgreSQL 的 WAL),把每一条 INSERT、UPDATE、DELETE 都转换成事件,推送到 Kafka。

Streaming 的核心机制是 Offset 管理。Debezium 会记录当前读取到的 binlog 位置(文件名 + 偏移量),定期提交到 Kafka 的 __consumer_offsets 主题或者一个独立的 Offset 存储中。这样即使进程重启,它也能从上次中断的地方继续读取,不会丢数据,也不会重复消费。

这里有个细节:

  • 至少一次语义:Debezium 默认保证事件至少被投递一次。也就是说,极端情况下可能会有重复事件,需要下游做幂等处理。
  • 顺序保证:同一个主键的变更事件,在同一个分区内是严格有序的。但如果你把表映射到多个分区,顺序就不保证了。

我的经验:Streaming 阶段最怕的是「断流」。我曾经遇到过 MySQL 主从切换后,binlog 文件名变了,Debezium 找不到对应的偏移量,直接报错退出。解决方案是配置 database.history.store.only.monitored.tables.ddl=true,并且把 Offset Topic 的副本数设成 3,保证高可用。

3.3 部署模式

Debezium 支持三种部署模式,每种都有它的脾气。我按使用频率从高到低给你捋一遍。

3.3.1 单机模式 (Standalone)

最简单的一种。一个进程,一个配置文件,跑起来就能用。适合开发测试、小规模场景。

# 启动命令
./bin/connect-standalone.sh config/connect-standalone.properties config/mysql-connector.properties

优点:部署快,调试方便。缺点:单点故障,没有高可用,扩缩容需要手动重启。

我个人只在本地开发时用这个模式。生产环境?别想了。

3.3.2 分布式模式 (Distributed)

这才是生产环境的正解。多个 Kafka Connect Worker 组成一个集群,Connector 和 Task 会在 Worker 之间自动分配。一个 Worker 挂了,它的任务会被其他 Worker 接管。

# 所有 Worker 使用相同的 group.id
group.id=debezium-cluster

# 配置 Offset、Config、Status 存储的 Kafka Topic
offset.storage.topic=debezium-offsets
config.storage.topic=debezium-configs
status.storage.topic=debezium-status

分布式模式下,你可以通过 REST API 动态管理 Connector:

# 创建 Connector
curl -X POST -H "Content-Type: application/json" \
  --data @mysql-connector.json \
  http://localhost:8083/connectors

# 查看 Connector 状态
curl http://localhost:8083/connectors/mysql-connector/status

我建议你至少部署 3 个 Worker 节点,配合 Kafka 的 3 副本,这样任何一个单点故障都不会影响数据同步。

3.3.3 嵌入式模式 (Embedded)

这种模式把 Debezium 直接嵌入到你的 Java 应用里。不需要 Kafka Connect 框架,你可以在代码里直接控制 Connector 的生命周期。

// 伪代码示例
DebeziumEngine<ChangeEvent<String, String>> engine = DebeziumEngine.create()
  .using(config)
  .notifying(record -> {
      // 直接处理变更事件
      System.out.println("Key: " + record.key() + ", Value: " + record.value());
  })
  .build();

engine.run();

嵌入式模式的好处是灵活,你可以把 CDC 能力直接集成到自己的微服务里。但坏处也很明显——你失去了 Kafka Connect 的集群管理、REST API、监控等能力。说白了,除非你有非常定制化的需求,否则我不推荐用嵌入式模式。

总结一下三种模式的选择:

  • 开发测试:单机模式,省事
  • 生产环境:分布式模式,稳
  • 特殊定制:嵌入式模式,但要做好自己造轮子的准备

3.4 本章小结

Debezium 的架构其实不复杂,核心就是 Connector + Snapshot + Streaming 这三个组件。Connector 负责对接数据源,Snapshot 搞定全量数据,Streaming 持续捕获增量变更。部署上,分布式模式是生产环境的标准答案。