1. Debezium 概述:CDC 概念、Debezium 架构、核心组件介绍

1.1 什么是 CDC?说白了就是“数据变,我就记”

CDC,全称 Change Data Capture,中文叫“变更数据捕获”。

你想想看,传统做法是怎么同步数据的?定时跑批,全量拉一遍。数据量小还行,一旦上了千万级,每次跑批都是对数据库的折磨。而且延迟至少几分钟到几小时,根本谈不上实时。

CDC 的思路完全不同——它只捕获变化的部分。插入、更新、删除,每一条变更都被记录下来,然后实时推送给下游。我习惯把 CDC 比作“数据库的日志订阅器”:你改了什么,我就知道什么,而且几乎零延迟。

CDC 的核心价值:

  • 实时性高:毫秒级延迟,不是分钟级
  • 对源库影响小:不锁表,不跑全量
  • 数据一致性:基于日志,不会丢数据

CDC 的实现方式主要有两种:基于查询的(比如轮询时间戳字段)和基于日志的。Debezium 走的是后者——直接读取数据库的事务日志。我在项目中遇到过用轮询方式做 CDC 的,结果每次查询都压垮主库,后来换成 Debezium,问题就解决了。

1.2 Debezium 是什么?一个“日志翻译官”

Debezium 是一个开源的分布式 CDC 平台,基于 Apache Kafka 构建。它的核心工作就是:把数据库的变更日志,翻译成 Kafka 能理解的消息。

说白了,Debezium 就是数据库和 Kafka 之间的桥梁。你不需要写任何代码去轮询数据库,也不需要自己去解析 binlog。Debezium 帮你搞定一切。

我个人习惯把 Debezium 比作“数据库的实时镜像管道”:

源库每产生一条变更,Debezium 就把它变成一条 JSON 或 Avro 格式的消息,发到 Kafka 里。下游的消费者(比如 Elasticsearch、数据仓库、缓存)直接订阅 Kafka 主题就行。

1.3 Debezium 架构:三个核心角色

Debezium 的架构其实不复杂。我画了一张图帮你理解:

Debezium 核心架构图 Debezium 核心架构 源数据库 MySQL / PostgreSQL / MongoDB ... binlog / WAL Debezium 连接器 解析日志 → 生成事件 Kafka Connect Apache Kafka 事件流 / Topic Elasticsearch 数据仓库 缓存 / Redis 其他系统 架构要点说明: 1. 源数据库产生变更日志(binlog / WAL / oplog) 2. Debezium 连接器作为 Kafka Connect 的 Source Connector 运行 3. 连接器将日志解析为结构化的 Change Event,写入 Kafka Topic 4. 下游消费者从 Kafka 订阅 Topic,实现实时数据同步

从图上你能看到,Debezium 架构主要分三层:

  • 源数据库层:MySQL、PostgreSQL、MongoDB、Oracle、SQL Server 等。Debezium 通过读取各自的事务日志来捕获变更。
  • Debezium 连接器层:这是核心。每个数据库类型对应一个连接器。连接器运行在 Kafka Connect 框架中,负责解析日志、生成事件。
  • Kafka 消息层:事件被写入 Kafka Topic。下游系统通过订阅 Topic 来消费数据。

注意:Debezium 本身不存储数据,它只是“翻译”和“转发”。数据持久化依赖 Kafka。所以 Kafka 的稳定性直接决定了 CDC 管道的可靠性。我曾经因为 Kafka 集群磁盘写满导致 Debezium 任务挂掉,那叫一个惨——恢复后还要处理积压的 binlog。

1.4 核心组件详解

Debezium 的组件其实不多,但每个都很关键。我按重要程度给你捋一遍:

组件 作用 我踩过的坑
Connector 每种数据库的专属连接器,负责读取日志并生成事件 MySQL Connector 需要开启 binlog_format=ROW,否则解析不了
Kafka Connect 运行连接器的分布式框架,提供 REST API 管理连接器 分布式模式下,连接器配置要小心 offset 存储,否则重启后重复消费
Change Event Debezium 输出的标准事件格式,包含 before/after 和元数据 默认 JSON 格式,字段名大小写敏感,下游解析时容易踩坑
Snapshot 连接器启动时对现有数据做一次全量快照 大表快照会占用大量资源,建议用 snapshot.mode=when_needed 控制
Offset 记录当前读取到的日志位置,用于故障恢复 offset 存储在 Kafka Topic 或文件里,丢失会导致重复或丢失数据

1.5 一个典型的 CDC 事件长什么样?

嗯,这里要给你看个实际例子。Debezium 输出的 Change Event 是结构化的 JSON,包含几个关键部分:

{
  "payload": {
    "before": null,                    // 变更前的数据(INSERT 时为 null)
    "after": {                         // 变更后的数据
      "id": 1001,
      "name": "张三",
      "email": "zhangsan@example.com",
      "created_at": "2024-01-15T10:30:00Z"
    },
    "source": {                        // 元数据:来自哪个库、哪个表、哪个位置
      "db": "ecommerce",
      "table": "users",
      "server_id": 1,
      "ts_ms": 1705300000000,
      "file": "mysql-bin.000123",
      "pos": 45678
    },
    "op": "c",                         // 操作类型:c=create, u=update, d=delete, r=snapshot
    "ts_ms": 1705300001000             // 事件生成时间戳
  }
}

我个人习惯:在生产环境中,我会把事件格式从 JSON 换成 Avro。虽然 Avro 需要 Schema Registry,但它的序列化效率高、schema 兼容性好,而且能避免 JSON 字段名大小写不一致的问题。

1.6 什么时候该用 Debezium?

不是所有场景都适合 CDC。我总结了几种典型场景:

  • 实时数据同步:从 MySQL 同步到 Elasticsearch,实现搜索实时更新
  • 缓存失效:数据库更新后,自动清除 Redis 缓存
  • 数据仓库实时入仓:把业务库的变更实时写入 ClickHouse、Doris 等分析引擎
  • 微服务事件驱动:一个服务修改数据后,通过 CDC 事件通知其他服务

避坑指南:我曾经在一个项目里,把 Debezium 用在了一个每天有 2 亿次写入的订单表上。结果 Kafka 的 Topic 分区数不够,消费者处理不过来,导致消息积压越来越严重。后来我调整了分区策略和消费者并发数,才把延迟降下来。所以,高吞吐场景下,一定要提前做好容量规划。

1.7 本章小结

这一章我们聊了 CDC 是什么、Debezium 怎么工作、以及它的核心组件。说白了,Debezium 就是帮你把数据库的变更日志变成实时数据流。你不需要写复杂的轮询代码,也不需要担心日志解析的细节。