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

说实话,搭建 CDC 管道这件事,60% 的坑都出在环境上。我见过太多人代码写好了,结果连不上 Kafka,或者 MySQL 的 binlog 没打开,折腾半天才发现是环境问题。所以这一章,咱们把地基打牢。

我会带你装好所有需要的组件。你跟着我的步骤走,基本不会出问题。嗯,咱们开始吧。

3.1 整体架构一览

在动手之前,你先想清楚我们要搭什么。说白了,就是让数据从 MySQL 流到 PostgreSQL,中间经过 Kafka 做缓冲和分发。这套东西跑在 Docker 里,用 Java 写的程序去控制它。

核心组件清单:

  • Docker + Docker Compose:容器编排,一键拉起所有服务
  • Java 11+:运行 Debezium 和 Kafka Connect
  • Apache Kafka:消息中间件,CDC 事件的核心通道
  • MySQL 8.0:源端数据库,开启 binlog
  • PostgreSQL 14:目标端数据库,接收变更

下面这张图,就是咱们整个环境的逻辑关系。你看一眼,心里有个谱。

CDC 增量同步环境架构图 CDC 增量同步环境架构图 MySQL 8.0 源端 · 开启 binlog Debezium Kafka Connect 连接器 Apache Kafka 消息中间件 PostgreSQL 14 目标端 Java 11+ 运行环境 binlog 读取 写入事件 消费写入 驱动 💡 说明: Debezium 作为 Kafka Connect 的连接器,监听 MySQL 的 binlog 变更。 变更事件被序列化为 Avro 或 JSON,写入 Kafka Topic。 下游消费者(如 JDBC Sink Connector)从 Kafka 读取并写入 PostgreSQL。

3.2 Docker 与 Docker Compose

我个人习惯用 Docker 来管理这些中间件。为什么?因为干净、可重复、不污染宿主机。你想想看,装一个 Kafka 要配 Zookeeper、调 JVM 参数、处理端口冲突……用 Docker 的话,一个 docker-compose.yml 全搞定。

3.2.1 安装 Docker

不同系统安装方式不一样。我列个表,你对照着来。

操作系统 安装方式 验证命令
macOS 下载 Docker Desktop 安装包 docker --version
Windows 下载 Docker Desktop,启用 WSL2 docker --version
Ubuntu/Debian sudo apt install docker.io sudo docker run hello-world
CentOS/RHEL sudo yum install docker-ce sudo systemctl status docker

我的建议:装好之后,记得把当前用户加到 docker 组,省得每次敲 sudo。

sudo usermod -aG docker $USER
newgrp docker

3.2.2 安装 Docker Compose

Docker Compose 现在已经是 Docker 的一部分了。如果你装的是 Docker Desktop,它自带 Compose。Linux 上可能需要单独装。

# 下载最新版
sudo curl -L "https://github.com/docker/compose/releases/latest/download/docker-compose-$(uname -s)-$(uname -m)" -o /usr/local/bin/docker-compose

# 赋予执行权限
sudo chmod +x /usr/local/bin/docker-compose

# 验证
docker-compose --version

⚠️ 注意:我曾经在 Ubuntu 20.04 上遇到过 Compose 版本太老的问题,导致 depends_on 条件不生效。建议直接装 v2 版本,命令是 docker compose(没有横杠)。

3.3 Java 环境

Debezium 和 Kafka Connect 都是 Java 写的。所以 Java 是必须的。我个人推荐 JDK 11,因为它在性能和兼容性上平衡得最好。JDK 8 太老,JDK 17 有些库还没完全适配。

3.3.1 安装 OpenJDK 11

# Ubuntu/Debian
sudo apt update
sudo apt install openjdk-11-jdk

# CentOS/RHEL
sudo yum install java-11-openjdk-devel

# 验证
java -version

输出应该类似这样:

openjdk version "11.0.18" 2023-01-17 LTS
OpenJDK Runtime Environment (build 11.0.18+10-post-Ubuntu-0ubuntu122.04)
OpenJDK 64-Bit Server VM (build 11.0.18+10-post-Ubuntu-0ubuntu122.04, mixed mode)

3.3.2 配置 JAVA_HOME

很多 Java 应用(包括 Kafka)依赖 JAVA_HOME 环境变量。不配的话,启动时会报错。我踩过这个坑,所以提醒你一下。

# 找到 Java 安装路径
sudo update-alternatives --config java

# 编辑 ~/.bashrc 或 ~/.zshrc
export JAVA_HOME=/usr/lib/jvm/java-11-openjdk-amd64
export PATH=$JAVA_HOME/bin:$PATH

# 生效
source ~/.bashrc

# 验证
echo $JAVA_HOME

3.4 Apache Kafka

Kafka 是整个 CDC 管道的核心。数据从 MySQL 出来,先到 Kafka,再到 PostgreSQL。为什么中间要加一层?说白了,为了解耦和缓冲。万一 PostgreSQL 挂了,数据不会丢,等它恢复后再继续消费。

3.4.1 用 Docker Compose 部署 Kafka

我建议用 Docker Compose 来部署 Kafka 和 Zookeeper。下面这个配置是我项目里常用的,你直接复制就行。

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

  kafka:
    image: confluentinc/cp-kafka:7.4.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_TRANSACTION_STATE_LOG_MIN_ISR: 1
      KAFKA_TRANSACTION_STATE_LOG_REPLICATION_FACTOR: 1

注意:KAFKA_ADVERTISED_LISTENERS 这个参数很关键。如果你在 Docker 里跑,客户端从宿主机连接时,需要暴露 localhost:9092。如果是在服务器上,要改成服务器的 IP 或域名。

3.4.2 启动并验证 Kafka

# 启动
docker-compose up -d

# 查看日志
docker-compose logs -f kafka

# 创建一个测试 Topic
docker exec -it kafka kafka-topics --create \
  --topic test-topic \
  --bootstrap-server localhost:9092 \
  --partitions 1 \
  --replication-factor 1

# 列出 Topic
docker exec -it kafka kafka-topics --list \
  --bootstrap-server localhost:9092

如果你看到 test-topic 出现在列表里,说明 Kafka 跑起来了。

3.5 MySQL 8.0

MySQL 是源端数据库。CDC 的核心是读取 binlog,所以 binlog 必须开启。我记得第一次做 CDC 项目时,忘了开 binlog,Debezium 连不上,查了半天才发现。嗯,这个坑你别踩。

3.5.1 用 Docker 部署 MySQL

version: '3.8'
services:
  mysql:
    image: mysql:8.0
    ports:
      - "3306:3306"
    environment:
      MYSQL_ROOT_PASSWORD: root123
      MYSQL_DATABASE: cdc_test
    command: --server-id=1 --log-bin=mysql-bin --binlog-format=ROW --binlog-row-image=FULL

关键参数说明:

  • --server-id=1:每个 MySQL 实例必须有唯一 ID,Debezium 靠它识别
  • --log-bin=mysql-bin:开启 binlog
  • --binlog-format=ROW:必须用 ROW 模式,CDC 才能读到每一行的变更
  • --binlog-row-image=FULL:记录完整的前后镜像,方便下游做对比

3.5.2 验证 binlog 是否开启

# 进入 MySQL 容器
docker exec -it mysql mysql -uroot -proot123

# 执行 SQL
SHOW VARIABLES LIKE 'log_bin';
SHOW VARIABLES LIKE 'binlog_format';

如果 log_bin 显示 ON,binlog_format 显示 ROW,那就对了。

3.5.3 创建 CDC 专用用户

Debezium 需要连接 MySQL 并读取 binlog。我建议创建一个专用用户,权限最小化。

CREATE USER 'cdc_user'@'%' IDENTIFIED BY 'cdc_pass';
GRANT SELECT, RELOAD, SHOW DATABASES, REPLICATION SLAVE, REPLICATION CLIENT ON *.* TO 'cdc_user'@'%';
FLUSH PRIVILEGES;

⚠️ 注意:不要用 root 用户。我曾经见过有人用 root 跑 CDC,结果误操作删了表……嗯,你懂的。权限最小化是安全底线。

3.6 PostgreSQL 14

PostgreSQL 是目标端。它负责接收从 Kafka 消费过来的变更数据。PostgreSQL 本身不需要特殊配置,但要注意一点:目标表的 schema 必须和源端匹配,否则写入会失败。

3.6.1 用 Docker 部署 PostgreSQL

version: '3.8'
services:
  postgres:
    image: postgres:14
    ports:
      - "5432:5432"
    environment:
      POSTGRES_USER: postgres
      POSTGRES_PASSWORD: postgres123
      POSTGRES_DB: cdc_target

3.6.2 验证连接

# 进入 PostgreSQL 容器
docker exec -it postgres psql -U postgres -d cdc_target

# 查看数据库
\l

# 退出
\q

看到 cdc_target 数据库,说明 PostgreSQL 跑起来了。

3.7 一键启动所有服务

好了,现在所有组件都准备好了。我把它们整合到一个 docker-compose.yml 里,你直接启动就行。

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

  kafka:
    image: confluentinc/cp-kafka:7.4.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_TRANSACTION_STATE_LOG_MIN_ISR: 1
      KAFKA_TRANSACTION_STATE_LOG_REPLICATION_FACTOR: 1

  mysql:
    image: mysql:8.0
    ports:
      - "3306:3306"
    environment:
      MYSQL_ROOT_PASSWORD: root123
      MYSQL_DATABASE: cdc_test
    command: --server-id=1 --log-bin=mysql-bin --binlog-format=ROW --binlog-row-image=FULL

  postgres:
    image: postgres:14
    ports:
      - "5432:5432"
    environment:
      POSTGRES_USER: postgres
      POSTGRES_PASSWORD: postgres123
      POSTGRES_DB: cdc_target

启动命令:

docker-compose up -d

等个 10 秒左右,所有服务就绪。你可以用 docker-compose ps 查看状态,四个服务都显示 Up 就对了。

3.8 环境验证清单

最后,我列一个验证清单。你对照着检查一遍,确保所有组件都正常工作。

组件 验证方式 预期结果
Docker docker --version 显示版本号
Docker Compose docker-compose --version 显示版本号
Java java -version 显示 OpenJDK 11
Kafka 创建 Topic 并列出 Topic 存在
MySQL 查看 binlog 状态 log_bin = ON
PostgreSQL 连接并查看数据库 cdc_target 存在