3. 环境搭建与快速入门:Flink环境安装、MySQL开启Binlog、Flink CDC Maven依赖、第一个DataStream CDC程序
好,咱们正式开始动手了。这一章的目标很明确——把环境搭起来,跑通第一个 CDC 程序。我见过不少同学在环境上卡一整天,其实说白了就几个关键点:Flink 版本别选错、MySQL Binlog 要开对、依赖别冲突。咱们一个一个来。
3.1 Flink 环境安装:别纠结,用 Standalone 模式就够了
Flink 的部署模式有好几种,YARN、Kubernetes、Standalone。对于学习和本地开发,我个人习惯用 Standalone 模式,简单直接,一条命令启动。
第一步:下载和解压
去 Flink 官网下载稳定版本。我建议用 1.17.x 或更新的版本,CDC 兼容性更好。
wget https://dlcdn.apache.org/flink/flink-1.17.2/flink-1.17.2-bin-scala_2.12.tgz
tar -xzf flink-1.17.2-bin-scala_2.12.tgz
cd flink-1.17.2
第二步:启动集群
./bin/start-cluster.sh
启动后访问 http://localhost:8081,看到 Flink Web UI 就说明成功了。
conf/flink-conf.yaml 里的 rest.port 和 jobmanager.rpc.port。
第三步:验证
./bin/flink run examples/streaming/WordCount.jar
看到控制台输出单词计数,环境就稳了。
3.2 MySQL 开启 Binlog:CDC 的数据源头
CDC 要捕获 MySQL 的变更,前提是 MySQL 开启了 Binlog。我记得第一次做 CDC 项目时,DBA 没开 Binlog,我排查了半天才发现……嗯,这个坑咱们提前避开。
检查当前 Binlog 状态
mysql> SHOW VARIABLES LIKE 'log_bin';
+---------------+-------+
| Variable_name | Value |
+---------------+-------+
| log_bin | OFF |
+---------------+-------+
如果是 OFF,需要修改 MySQL 配置文件(my.cnf 或 my.ini)。
开启 Binlog 配置
[mysqld]
server-id = 1
log_bin = mysql-bin
binlog_format = ROW
binlog_row_image = FULL
expire_logs_days = 7
binlog_format 必须设置为 ROW,Flink CDC 只支持 ROW 格式。STATEMENT 和 MIXED 格式会导致数据不一致。
重启 MySQL 并验证
mysql> SHOW MASTER STATUS;
+------------------+----------+--------------+------------------+-------------------+
| File | Position | Binlog_Do_DB | Binlog_Ignore_DB | Executed_Gtid_Set |
+------------------+----------+--------------+------------------+-------------------+
| mysql-bin.000001 | 154 | | | |
+------------------+----------+--------------+------------------+-------------------+
看到 File 和 Position 有值,Binlog 就正常工作了。
3.3 Flink CDC Maven 依赖:版本匹配是关键
依赖配置是新手最容易踩坑的地方。我曾经见过有人把 Flink 1.14 和 CDC 2.4 混用,结果跑起来全是序列化异常。这里我直接给出一套经过验证的依赖组合。
核心依赖(基于 Flink 1.17 + CDC 2.4)
<properties>
<flink.version>1.17.2</flink.version>
<cdc.version>2.4.0</cdc.version>
<scala.binary.version>2.12</scala.binary.version>
</properties>
<dependencies>
<!-- Flink 核心 -->
<dependency>
<groupId>org.apache.flink</groupId>
<artifactId>flink-streaming-java</artifactId>
<version>${flink.version}</version>
</dependency>
<dependency>
<groupId>org.apache.flink</groupId>
<artifactId>flink-clients</artifactId>
<version>${flink.version}</version>
</dependency>
<!-- Flink CDC -->
<dependency>
<groupId>com.ververica</groupId>
<artifactId>flink-connector-mysql-cdc</artifactId>
<version>${cdc.version}</version>
</dependency>
<!-- MySQL JDBC 驱动 -->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>8.0.33</version>
</dependency>
</dependencies>
| Flink 版本 | CDC 推荐版本 | Scala 版本 |
|---|---|---|
| 1.14.x | 2.2.x | 2.12 |
| 1.15.x | 2.3.x | 2.12 |
| 1.16.x | 2.3.x / 2.4.x | 2.12 |
| 1.17.x | 2.4.x | 2.12 |
3.4 第一个 DataStream CDC 程序:从 MySQL 读取变更
环境搭好了,依赖配好了,咱们写个最简单的程序——监听 MySQL 的一张表,把增删改查打印出来。
准备测试表
CREATE DATABASE flink_cdc_demo;
USE flink_cdc_demo;
CREATE TABLE users (
id INT PRIMARY KEY AUTO_INCREMENT,
name VARCHAR(50),
email VARCHAR(100),
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);
INSERT INTO users(name, email) VALUES('Alice', 'alice@example.com');
INSERT INTO users(name, email) VALUES('Bob', 'bob@example.com');
编写 CDC 程序
import org.apache.flink.streaming.api.environment.StreamExecutionEnvironment;
import com.ververica.cdc.connectors.mysql.source.MySqlSource;
import com.ververica.cdc.debezium.JsonDebeziumDeserializationSchema;
import org.apache.flink.api.common.eventtime.WatermarkStrategy;
public class MySqlCdcDemo {
public static void main(String[] args) throws Exception {
// 1. 创建执行环境
StreamExecutionEnvironment env = StreamExecutionEnvironment.getExecutionEnvironment();
env.setParallelism(1);
// 2. 配置 MySQL CDC Source
MySqlSource<String> mySqlSource = MySqlSource.<String>builder()
.hostname("localhost")
.port(3306)
.databaseList("flink_cdc_demo")
.tableList("flink_cdc_demo.users")
.username("root")
.password("your_password")
.deserializer(new JsonDebeziumDeserializationSchema())
.build();
// 3. 读取数据流
env.fromSource(mySqlSource, WatermarkStrategy.noWatermarks(), "MySQL CDC Source")
.print();
// 4. 执行
env.execute("Flink CDC Demo");
}
}
运行程序
在 MySQL 里执行一些变更操作:
INSERT INTO users(name, email) VALUES('Charlie', 'charlie@example.com');
UPDATE users SET email = 'alice_new@example.com' WHERE id = 1;
DELETE FROM users WHERE id = 2;
控制台会输出类似这样的 JSON:
{
"before": null,
"after": {
"id": 3,
"name": "Charlie",
"email": "charlie@example.com",
"created_at": 1695000000000
},
"op": "c"
}
{
"before": {
"id": 1,
"name": "Alice",
"email": "alice@example.com"
},
"after": {
"id": 1,
"name": "Alice",
"email": "alice_new@example.com"
},
"op": "u"
}
{
"before": {
"id": 2,
"name": "Bob",
"email": "bob@example.com"
},
"after": null,
"op": "d"
}
op 字段表示操作类型:c 是新增,u 是更新,d 是删除。你看,MySQL 里的每一次变更,都实时地流到了 Flink 里。
3.5 核心流程一览
下面这张图把整个 CDC 数据流串起来了,你一看就明白。
3.6 避坑指南
- MySQL 用户权限: CDC 用户需要
SELECT、REPLICATION SLAVE、REPLICATION CLIENT权限。我曾经因为漏了REPLICATION SLAVE,程序一直连不上 Binlog。 - 并行度设置: MySQL CDC Source 的并行度不能超过表的数量。如果你只监听一张表,并行度设为 1 最稳。
- 时区问题: Flink CDC 默认使用 UTC 时区。如果你的 MySQL 是东八区,记得在连接参数里加
?serverTimezone=Asia/Shanghai。 - 大表初始化: 第一次启动 CDC 时,Flink 会先做一次全量快照,再切换到增量 Binlog。如果表很大,建议先做一次
SELECT COUNT(*)评估数据量。
好了,环境搭好了,第一个程序也跑通了。你现在应该能感受到 CDC 的魅力——数据库的每一次变更,都像流水一样实时流到你的面前。后面咱们会在这个基础上,做更复杂的处理和落地。