3. 环境准备:Docker、Kafka、MySQL、PostgreSQL、Debezium Connector 的安装与配置

好,咱们正式开始动手。这一章说白了就是搭积木,把 CDC 全链路需要的所有组件装好、配通。我见过不少同学在环境上卡一整天,其实只要理清顺序,半小时就能跑起来。

先看整体架构,心里有个地图:

CDC 全链路环境组件图 MySQL 源库 binlog 生产者 PostgreSQL 源库 WAL 生产者 Debezium Connector CDC 采集引擎 Kafka 消息总线 Docker + Docker Compose 运行环境 容器化部署,统一管理所有组件 💡 部署顺序: Docker → Kafka + Zookeeper → MySQL → PostgreSQL → Debezium Connector(Kafka Connect)

3.1 Docker 与 Docker Compose

我个人习惯,所有 CDC 实验环境都用 Docker 跑。为什么?你想想看,要是每台机器都手动装 Kafka、装数据库,光依赖冲突就能折腾半天。容器化之后,一个 docker-compose up 全部搞定。

安装其实没啥难度,但版本要注意:

组件推荐版本说明
Docker Engine24.x 及以上老版本网络性能差,我踩过坑
Docker Composev2.x别用 v1 了,语法都不一样

验证安装:

docker --version
docker compose version

能正常输出版本号,就说明环境就绪了。

3.2 Kafka 与 Zookeeper

Kafka 是 CDC 数据的"高速公路"。Debezium 采集到的变更事件,全部先发到 Kafka,再由下游消费。这里有个关键点——Kafka 依赖 Zookeeper 做协调,虽然新版本在逐步去 ZK,但生产环境还是 ZK 模式最稳。

我曾经遇到过 Kafka 集群脑裂,就是因为 ZK 配置没调好。所以建议你直接用官方镜像,别自己编译。

docker-compose 配置片段:

version: '3.8'
services:
  zookeeper:
    image: confluentinc/cp-zookeeper:7.6.0
    environment:
      ZOOKEEPER_CLIENT_PORT: 2181
      ZOOKEEPER_TICK_TIME: 2000

  kafka:
    image: confluentinc/cp-kafka:7.6.0
    depends_on:
      - zookeeper
    ports:
      - "9092:9092"
    environment:
      KAFKA_BROKER_ID: 1
      KAFKA_ZOOKEEPER_CONNECT: zookeeper:2181
      KAFKA_ADVERTISED_LISTENERS: PLAINTEXT://localhost:9092
      KAFKA_OFFSETS_TOPIC_REPLICATION_FACTOR: 1

⚠️ 注意:KAFKA_ADVERTISED_LISTENERS 必须配成客户端能访问的地址。如果你用 Docker Desktop,就写 localhost;如果是远程服务器,写公网 IP 或内网 IP。我见过有人配成容器内网 IP,结果客户端连不上,排查了半天。

3.3 MySQL 源库配置

MySQL 作为 CDC 源,核心是开启 binlog。说白了,binlog 就是 MySQL 的"操作日志",Debezium 就是靠读这个日志来捕获变更的。

配置要点:

  • binlog_format 必须设为 ROW,否则拿不到完整的前后镜像
  • binlog_row_image 设为 FULL,确保 UPDATE 和 DELETE 事件包含所有列
  • 给 Debezium 创建一个专用账号,权限只需要 REPLICATION SLAVE、REPLICATION CLIENT 和 SELECT

docker-compose 配置:

mysql:
  image: mysql:8.0
  ports:
    - "3306:3306"
  environment:
    MYSQL_ROOT_PASSWORD: root123
  command: |
    --server-id=1
    --log-bin=mysql-bin
    --binlog-format=ROW
    --binlog-row-image=FULL
    --expire-logs-days=7

验证 binlog 是否开启:

mysql -uroot -proot123 -e "SHOW VARIABLES LIKE 'log_bin';"

返回 ON 就对了。

3.4 PostgreSQL 源库配置

PostgreSQL 的 CDC 机制和 MySQL 不太一样。它用的是 WAL(预写日志),需要把复制级别调到 logical。嗯,这里有个坑——逻辑复制槽,如果 Debezium 挂了,复制槽不释放,WAL 会一直堆积,最后把磁盘撑爆。

配置要点:

  • wal_level = logical 开启逻辑复制
  • max_replication_slots = 10 至少留 1 个给 Debezium
  • max_wal_senders = 10 允许并发 WAL 发送

docker-compose 配置:

postgres:
  image: postgres:16
  ports:
    - "5432:5432"
  environment:
    POSTGRES_PASSWORD: postgres123
  command: |
    -c wal_level=logical
    -c max_replication_slots=10
    -c max_wal_senders=10

⚠️ 避坑:我曾经在生产环境遇到过复制槽不释放导致 WAL 堆积,磁盘报警。建议你设置 wal_keep_size 限制 WAL 保留量,或者写个定时任务监控复制槽状态。

3.5 Debezium Connector(Kafka Connect)

Debezium 本身不是一个独立服务,它运行在 Kafka Connect 框架里。说白了,Kafka Connect 是个"插件平台",Debezium 就是其中一个插件。

部署方式有两种:

方式优点缺点
独立 Kafka Connect 集群资源隔离,适合生产多维护一个集群
嵌入 Kafka 进程简单,适合实验耦合度高,不好扩展

我个人建议实验阶段用独立集群,方便调试。配置如下:

connect:
  image: debezium/connect:2.5
  ports:
    - "8083:8083"
  environment:
    BOOTSTRAP_SERVERS: kafka:9092
    GROUP_ID: 1
    CONFIG_STORAGE_TOPIC: connect-configs
    OFFSET_STORAGE_TOPIC: connect-offsets
    STATUS_STORAGE_TOPIC: connect-status
  depends_on:
    - kafka

启动后,通过 REST API 注册 Connector:

curl -X POST http://localhost:8083/connectors \
  -H "Content-Type: application/json" \
  -d '{
    "name": "mysql-connector",
    "config": {
      "connector.class": "io.debezium.connector.mysql.MySqlConnector",
      "database.hostname": "mysql",
      "database.port": "3306",
      "database.user": "debezium",
      "database.password": "dbz123",
      "database.server.id": "1",
      "database.server.name": "dbserver1",
      "database.include.list": "testdb",
      "table.include.list": "testdb.orders",
      "database.history.kafka.bootstrap.servers": "kafka:9092",
      "database.history.kafka.topic": "schema-changes.testdb"
    }
  }'

验证 Connector 是否运行:

curl http://localhost:8083/connectors/mysql-connector/status

返回 "state": "RUNNING" 就说明采集成功了。

3.6 一键启动与验证

所有配置写到一个 docker-compose.yml 里,然后:

docker compose up -d

等 30 秒左右,检查所有容器状态:

docker compose ps

你应该看到 5 个容器都在 Up 状态:zookeeper、kafka、mysql、postgres、connect。

最后,往 MySQL 里插一条数据测试:

mysql -uroot -proot123 testdb -e "INSERT INTO orders(id, product, amount) VALUES(1, 'book', 29.9);"

然后消费 Kafka 主题看看:

docker compose exec kafka kafka-console-consumer \
  --bootstrap-server localhost:9092 \
  --topic dbserver1.testdb.orders \
  --from-beginning

如果看到 JSON 格式的变更事件,恭喜你——CDC 全链路已经跑通了。

环境就绪清单:

  • ✅ Docker + Docker Compose 安装完成
  • ✅ Kafka + Zookeeper 集群启动
  • ✅ MySQL 开启 binlog,创建专用账号
  • ✅ PostgreSQL 开启逻辑复制
  • ✅ Debezium Connector 注册成功,状态 RUNNING
  • ✅ 数据变更事件成功写入 Kafka