4. Debezium深度解析
Debezium 这个项目,说白了就是 CDC 领域的事实标准。我最早接触它是在 2018 年,那时候公司要做 MySQL 到 Elasticsearch 的实时同步,调研了一圈,最后还是选了它。为什么?因为它把最麻烦的 binlog 解析、offset 管理、schema 变更这些事情都封装好了,你只需要关心业务逻辑。
这一章,我会把 Debezium 的核心架构、两种连接器模式,以及后来推出的 Server 模式讲清楚。嗯,都是我在生产环境里踩过坑之后的理解。
Debezium 架构原理
Debezium 本质上是一组 Kafka Connect 的连接器。它利用数据库的日志(比如 MySQL 的 binlog、PostgreSQL 的 WAL)来捕获变更事件,然后把这些事件转换成结构化的消息,推送到 Kafka。
它的核心架构可以分成三层:
- Connector 层:负责与数据库交互,读取日志,解析事件。每个数据库类型都有自己的 Connector。
- 转换层:将原始日志事件转换成 Debezium 的通用数据模型,包含 schema、payload、source 元数据。
- 发送层:通过 Kafka Connect 的框架,将转换后的消息写入 Kafka 指定的 topic。
我画了一张架构图,你可以直观地看到数据是怎么流动的:
这里有个关键点:Debezium 会记录它读取日志的位置(offset)。如果进程挂了,重启后它会从上次记录的位置继续读取,不会丢数据。我在项目中遇到过因为磁盘写满导致 Connector 挂掉的情况,重启后它自动从断点恢复,一条数据都没丢。这个机制很可靠。
核心要点:Debezium 的 offset 管理是它高可靠性的基石。它把 offset 存储在 Kafka 的 __consumer_offsets 主题或者一个独立的文件中,确保 exactly-once 语义。
Source Connector 与 Sink Connector
Debezium 的连接器分为两类:Source Connector 和 Sink Connector。很多人搞混,我简单说一下。
Source Connector
Source Connector 是 Debezium 的主力。它负责从数据库读取日志,把变更事件推送到 Kafka。目前官方支持的 Source Connector 包括:
| 连接器名称 | 支持的数据库 | 日志类型 | 生产环境成熟度 |
|---|---|---|---|
| Debezium MySQL Connector | MySQL 5.7+ / MariaDB | binlog | ★★★★★ |
| Debezium PostgreSQL Connector | PostgreSQL 9.6+ | WAL (pgoutput) | ★★★★★ |
| Debezium MongoDB Connector | MongoDB 3.6+ | oplog / Change Streams | ★★★★☆ |
| Debezium SQL Server Connector | SQL Server 2016+ | CDC 表 | ★★★★☆ |
| Debezium Oracle Connector | Oracle 12c+ | LogMiner / XStream | ★★★☆☆ |
配置一个 Source Connector 其实不复杂。我给你看一个 MySQL Connector 的典型配置:
{
"name": "mysql-connector",
"config": {
"connector.class": "io.debezium.connector.mysql.MySqlConnector",
"database.hostname": "192.168.1.100",
"database.port": "3306",
"database.user": "debezium",
"database.password": "debezium_pwd",
"database.server.id": "184054",
"database.server.name": "myapp",
"database.include.list": "mydb",
"table.include.list": "mydb.orders,mydb.users",
"database.history.kafka.bootstrap.servers": "kafka:9092",
"database.history.kafka.topic": "schema-changes.mydb",
"include.schema.changes": "true",
"snapshot.mode": "initial"
}
}
这里有个坑:database.server.name 这个参数决定了 Kafka topic 的前缀。比如你设成 myapp,那 orders 表的变更就会发到 myapp.mydb.orders 这个 topic。我曾经见过有人把这个名字设成中文,结果 Kafka 直接报错。嗯,记住,只能用字母、数字和下划线。
Sink Connector
Sink Connector 是反向的。它从 Kafka 读取数据,写入到其他系统,比如 Elasticsearch、HDFS、JDBC 数据库等。Debezium 本身不提供 Sink Connector,但 Kafka Connect 生态里有大量的现成实现。
我个人习惯把 Debezium 的 Source Connector 和 Sink Connector 组合使用,形成一条完整的 CDC 管道:
- Source 端:Debezium MySQL Connector 捕获 binlog 变更,写入 Kafka。
- Sink 端:Kafka Connect Elasticsearch Sink Connector 从 Kafka 读取数据,写入 Elasticsearch。
这样做的好处是解耦。Source 和 Sink 可以独立扩缩容,互不影响。
小技巧:如果你需要把数据写入多个目标系统,只需要启动多个 Sink Connector 即可。它们可以消费同一个 Kafka Topic,互不干扰。
Debezium Server 模式
传统的 Debezium 必须依赖 Kafka Connect 框架运行。但有些场景下,你不想引入 Kafka,或者你的下游系统不是 Kafka。这时候,Debezium Server 模式就派上用场了。
Debezium Server 是一个独立的 Java 应用,它内置了 Source Connector,可以直接从数据库读取变更,然后通过你指定的 Sink 写入到目标系统。它支持的 Sink 包括:
- Kafka:写入 Kafka Topic
- Pulsar:写入 Apache Pulsar
- Google Cloud Pub/Sub:写入 GCP 消息队列
- Amazon Kinesis:写入 AWS Kinesis
- Redis Streams:写入 Redis Stream
- 文件系统:写入本地文件(JSON 或 Avro 格式)
它的配置方式也很简单。你只需要一个 application.properties 文件:
# Debezium Server 配置示例
debezium.source.connector.class=io.debezium.connector.mysql.MySqlConnector
debezium.source.database.hostname=192.168.1.100
debezium.source.database.port=3306
debezium.source.database.user=debezium
debezium.source.database.password=debezium_pwd
debezium.source.database.server.id=184055
debezium.source.database.server.name=myapp
debezium.source.database.include.list=mydb
debezium.source.table.include.list=mydb.orders
# Sink 配置:写入 Redis Stream
debezium.sink.type=redis
debezium.sink.redis.address=redis://192.168.1.200:6379
debezium.sink.redis.key.format=stream:mydb:orders
启动命令也很直接:
java -jar debezium-server-2.5.0.Final.jar
我在一个 IoT 项目里用过 Debezium Server 模式。当时客户不想用 Kafka,觉得太重了。我就用 Debezium Server 直接把 MySQL 的变更推送到 Redis Stream,前端通过 WebSocket 订阅 Redis,实现了毫秒级的实时数据展示。整个架构非常轻量。
注意事项:Debezium Server 模式虽然方便,但它没有 Kafka Connect 那样的分布式协调能力。如果单机挂了,你需要手动重启。生产环境建议配合容器编排工具(如 Docker Compose 或 Kubernetes)来保证高可用。
最后总结一下:Source Connector 是 Debezium 的核心,负责捕获数据;Sink Connector 负责分发数据;Server 模式则是一个轻量级的替代方案,适合不想引入 Kafka 的场景。你想想看,根据你的业务需求,选择最合适的模式就行。