前言
声明:
本文主要文本内容由AI生成,然后手动进行修正并多次测试通过
此教学中的各种信息:
- 打算安装的Flink:版本1.18.1 | 安装位置:docker
- 系统:Win11
- MySQL:版本8.x | 安装位置:宿主机
- Docker:server:27.4.0 | client:27.4.0
建议测试用的库/表/MySQL用户等均与本文保持一致,先跑起来再说
数据准备
请先准备以下数据:- 你要监控的 MySQL 表的具体信息(第一次使用Flink建议先按照本文的库/表来创建并测试):
- 数据库名称 (Database Name):例如 test_db。
- 表名称 (Table Name):例如 target_table;。
- 表的结构 (Schema):即表包含哪些列,以及每一列的数据类型。例如:
- 你的MySQL的时区
- 如何查看:
- 在MySQL命令行中执行以下命令
- 如何查看:
SELECT @@global.time_zone, @@session.time_zone;
* 如果和我一样为SYSTEM,则在CMD/PowerShell中执行查看系统时区名称
tzutil /g
* 不管显示的是否是SYSTEM,都在获取名称后把命名和执行结果一起丢给AI,让AI生成对应的<font style="color:rgba(0, 0, 0, 0.9);background-color:rgb(243, 243, 243);">IANA 时区标识符</font>
开始配置
MySQL
**第一步:配置宿主机 MySQL 以支持 CDC**
Flink 要想监测到 MySQL 的数据变更,MySQL 本身需要启用二进制日志 (`binlog`),并且配置为 `ROW` 格式。- 修改 MySQL 配置文件 (
my.ini
):- 在 Windows 上,
my.ini
文件通常位于 MySQL 的安装目录下 (例如C:\Program Files\MySQL\MySQL Server X.Y\my.ini
) 或数据目录下 (C:\ProgramData\MySQL\MySQL Server X.Y\my.ini
)。请找到它。 - 用文本编辑器打开
my.ini
,找到[mysqld]
配置段。 - 添加或修改以下配置项:
- 在 Windows 上,
[mysqld]
# binlog 相关配置
server_id = 1 # 确保这是一个唯一的整数 ID,如果您的网络中还有其他 MySQL 主从复制,请选择一个不冲突的 ID
log_bin = mysql-bin # 启用 binlog,并指定 binlog 文件的前缀
binlog_format = ROW # 设置 binlog 格式为 ROW
binlog_row_image = FULL # 记录完整的行镜像,CDC 需要
# GTID (推荐,尤其对于较新版本的 MySQL 和 CDC Connector)
gtid_mode = ON
enforce_gtid_consistency = ON
# 其他您已有的配置...
- 保存并关闭 `my.ini` 文件。
- 重启 MySQL 服务:
- 打开 Windows 的 “服务” (Services)。可以按
Win + R
,输入services.msc
并回车。 - 在服务列表中找到您的 MySQL 服务 (通常名为 “MySQL” 或类似 “MySQL80” 的名称)。
- 右键点击该服务,选择 “重新启动”。
- 其他方法可自己询问AI。
- 打开 Windows 的 “服务” (Services)。可以按
- 创建 MySQL 的用户并授权:
- 该用户用于Flink程序访问MySQL数据库,执行数据读取(Source)或写入(Sink)操作。
- 本文设定用户名和密码都是
canal
。现在我们来创建这个用户并授予必要的权限。 - 在MySQL的命令行中执行以下 SQL 命令:
-- 创建用户 'canal',允许从任何主机 (%) 连接,密码为 'canal'
-- 如果您希望更安全,可以将 '%' 替换为 Docker 容器可能使用的 IP 地址段,
-- 但对于本地测试,'%' 或 'host.docker.internal' (如果 MySQL 版本较新且配置正确) 通常可行。
-- Flink 容器将使用 'host.docker.internal' 访问宿主机,MySQL 侧用户可以指定为 'canal'@'%' 或 'canal'@'docker_host_ip'
CREATE USER 'canal'@'%' IDENTIFIED BY 'canal';
-- 授予必要的权限
GRANT SELECT, RELOAD, SHOW DATABASES, REPLICATION SLAVE, REPLICATION CLIENT, LOCK TABLES ON *.* TO 'canal'@'%';
-- 刷新权限
FLUSH PRIVILEGES;
- 验证
binlog
是否开启 (可选,但推荐):
SHOW VARIABLES LIKE 'log_bin';
-- 应该显示 log_bin 为 ON
SHOW VARIABLES LIKE 'binlog_format';
-- 应该显示 binlog_format 为 ROW
SHOW VARIABLES LIKE 'binlog_row_image';
-- 应该显示 binlog_row_image 为 FULL
Flink
**第二步:在 Docker 中安装和启动 Flink 1.18.1**
我们将使用 Docker 来运行 Flink JobManager 和 TaskManager。- 拉取 Flink 1.18.1 Docker 镜像:
打开 PowerShell 或命令提示符,执行:
docker pull flink:1.18.1-scala_2.12-java11
(我们选择带有 Scala 2.12 和 Java 11 的镜像,这是一个常用且稳定的组合)
- 启动 Flink JobManager 容器:
docker run -d --name flink-jobmanager -p 8081:8081 --add-host=host.docker.internal:host-gateway -e JOB_MANAGER_RPC_ADDRESS=flink-jobmanager flink:1.18.1-scala_2.12-java11 jobmanager
docker run -d \
--name flink-jobmanager \
-p 8081:8081 \
--add-host=host.docker.internal:host-gateway \
-e JOB_MANAGER_RPC_ADDRESS=flink-jobmanager \
flink:1.18.1-scala_2.12-java11 jobmanager
- `-d`: 后台运行容器。
- `--name flink-jobmanager`: 给容器命名。
- `-p 8081:8081`: 将容器的 8081 端口映射到宿主机的 8081 端口 (Flink Web UI)。
- `--add-host=host.docker.internal:host-gateway`: 允许容器通过 `host.docker.internal` 这个特殊 DNS 名称访问宿主机上的服务 (即MySQL)。
- `-e JOB_MANAGER_RPC_ADDRESS=flink-jobmanager`将其 RPC 地址配置为 TaskManager 用来连接它的地址 (flink-jobmanager)。
- `flink:1.18.1-scala_2.12-java11`: 使用的镜像。
- `jobmanager`: 指定容器运行 JobManager。
- 启动 Flink TaskManager 容器:
docker run -d --name flink-taskmanager --add-host=host.docker.internal:host-gateway --link flink-jobmanager:jobmanager -e JOB_MANAGER_RPC_ADDRESS=flink-jobmanager flink:1.18.1-scala_2.12-java11 taskmanager
docker run -d \
--name flink-taskmanager \
--add-host=host.docker.internal:host-gateway \
--link flink-jobmanager:jobmanager \
-e JOB_MANAGER_RPC_ADDRESS=flink-jobmanager \
flink:1.18.1-scala_2.12-java11 taskmanager
- `-d`: 后台运行容器。
- `--name flink-taskmanager`: 给容器命名。
- `--add-host=host.docker.internal:host-gateway`: 允许容器通过 `host.docker.internal` 这个特殊 DNS 名称访问宿主机上的服务 (即MySQL)。
- `--link flink-jobmanager:jobmanager`: 将此 TaskManager 连接到之前启动的 JobManager。
- `-e JOB_MANAGER_RPC_ADDRESS=flink-jobmanager`:
* -e 用于设置环境变量。
* JOB_MANAGER_RPC_ADDRESS 是 Flink Docker 脚本用来覆盖 jobmanager.rpc.address 配置项的环境变量。设置为 flink-jobmanager。这是 JobManager 容器的 --name。Docker 的内部网络通常允许容器通过服务名进行通信。
* 我们将其设置为 flink-jobmanager,这样 TaskManager 就会去连接名为 flink-jobmanager 的主机。
* 我们仍然保留 --link flink-jobmanager:jobmanager,虽然 jobmanager 这个别名现在不直接用于 JOB_MANAGER_RPC_ADDRESS,但它确保了 flink-jobmanager 这个名称在 TaskManager 的 /etc/hosts 文件中被正确解析。
- `flink:1.18.1-scala_2.12-java11`: 使用的镜像。
- `taskmanager`: 指定容器运行 TaskManager。
- 两个容器的交互(可看可不看,还没讲明白):
- 通过为 JobManager 设置 JOB_MANAGER_RPC_ADDRESS=flink-jobmanager,我们告诉 JobManager “当启动你的 RPC 服务时,你应该认为自己的地址是 flink-jobmanager”。
- 通过为 TaskManager 设置 JOB_MANAGER_RPC_ADDRESS=flink-jobmanager,我们告诉 TaskManager “去连接名为 flink-jobmanager 的 JobManager”。
- –link flink-jobmanager:jobmanager 确保了 flink-jobmanager 这个名称在 TaskManager 容器内部可以被解析到 JobManager 容器的 IP 地址。
- 验证 Flink 集群是否运行:
- 打开浏览器,访问
http://localhost:8081
。您应该能看到 Flink 的 Web UI。 - 在 UI 中,检查 “Task Managers” 部分,应该能看到一个可用的 TaskManager。
- 打开浏览器,访问
- 进入 JobManager 容器,并使用
wget
下载 Connector JAR 文件:- 首先,进入容器的 shell:
docker exec -it flink-jobmanager /bin/bash
(如果 /bin/bash
不存在,可以尝试 /bin/sh
)
- 在容器的 shell 中执行:
# 检查 wget 是否可用,通常 Flink 官方镜像是包含的
# 如果 wget 不存在,可能需要先 apt-get update && apt-get install -y wget (如果镜像是基于 Debian/Ubuntu)
# 但我们先假设 wget 可用
cd /opt/flink/lib
wget https://repo1.maven.org/maven2/com/ververica/flink-sql-connector-mysql-cdc/3.0.1/flink-sql-connector-mysql-cdc-3.0.1.jar
# 验证文件是否下载成功并且大小合理
ls -l flink-sql-connector-mysql-cdc-3.0.1.jar
# 下载完成后,使用 exit 命令退出容器的 shell。
exit
- 进入
flink-taskmanager
容器内部下载 CDC Connector JAR 文件:- 首先,进入容器的 shell:
docker exec -u 0 -it flink-taskmanager /bin/bash
- 注意这里使用了 `-u 0` 以 `root` 用户身份进入,确保有权限在 `/opt/flink/lib/` 目录下创建文件。
- 在容器的 shell 中执行:
# 在容器内部执行
cd /opt/flink/lib
wget https://repo1.maven.org/maven2/com/ververica/flink-sql-connector-mysql-cdc/3.0.1/flink-sql-connector-mysql-cdc-3.0.1.jar
# wget https://repo.maven.apache.org/maven2/com/ververica/flink-sql-connector-mysql-cdc/3.0.1/flink-sql-connector-mysql-cdc-3.0.1.jar
exit
- 重启 JobManager 和 TaskManager 容器:
为了确保 Flink 进程在启动时能加载新下载到/opt/flink/lib
目录中的 JAR 文件,最稳妥的方式是重启容器。
docker restart flink-jobmanager
docker restart flink-taskmanager
等待几秒钟让它启动。
- 验证 TaskManager 的类路径(可选):
等待 TaskManager 启动后,立即查看其最新的日志,并特别关注启动时打印的Classpath
信息,确保flink-sql-connector-mysql-cdc-3.0.1.jar
已经包含在内(可直接把日志丢给AI,让AI判断是否成功启动):
docker logs flink-taskmanager
**第三步:编写并执行 Flink SQL 作业**
现在我们将使用 Flink SQL 客户端来定义数据源 (MySQL) 和数据汇 (打印到控制台),并运行一个查询。- 启动 Flink SQL 客户端:
在 PowerShell 或命令提示符中执行:
docker exec -it flink-jobmanager /opt/flink/bin/sql-client.sh
成功后,您会看到 Flink SQL 客户端的提示符,如 Flink SQL>
。
- `docker exec -it flink-jobmanager`: 在运行的 `flink-jobmanager` 容器内执行命令。
- `/opt/flink/bin/sql-client.sh`: Flink SQL 客户端的路径。
- 在 Flink SQL 客户端中执行以下 DDL 和 DML 语句:
- 创建 MySQL CDC 源表 (
mysql_source_target_table
):
将下面的 SQL 粘贴到 Flink SQL 客户端并执行。这条语句告诉 Flink如何连接到您的 MySQL 表并读取变更数据。
- 创建 MySQL CDC 源表 (
-- DROP TABLE IF EXISTS print_sink; -- 确保从干净状态开始
-- DROP TABLE IF EXISTS mysql_source_target_table; -- 确保从干净状态开始
-- 重新创建 mysql_source_target_table,注意 op_ts 的元数据键已修改
CREATE TABLE mysql_source_target_table (
id INT,
data STRING,
op_ts TIMESTAMP(3) METADATA FROM 'op_ts' VIRTUAL, -- 新的,正确的元数据键
PRIMARY KEY (id) NOT ENFORCED
) WITH (
'connector' = 'mysql-cdc',
'hostname' = 'host.docker.internal', -- 你的MySQL的IP/域名
'port' = '3306', -- 你的MySQL端口
'username' = 'canal', -- 《创建 MySQL 的用户并授权》步骤中创建的用户
'password' = 'canal',
'database-name' = 'test_db', -- 要监听的表所属数据库
'table-name' = 'target_table', -- 要监听的表
'server-time-zone' = 'Asia/Shanghai', -- 改为自己的时区,C:\Users\34362>tzutil /g
'scan.startup.mode' = 'initial' -- 以上命令输出:China Standard Time,获取后向AI询问对应的IANA 时区标识符
);
-- 重新创建 print_sink 表
CREATE TABLE print_sink (
id INT,
data STRING,
op_ts TIMESTAMP(3), -- 注意这里的 op_ts 是一个普通列,它将接收来自源表的 op_ts 值
PRIMARY KEY (id) NOT ENFORCED
) WITH (
'connector' = 'print'
);
-- 执行 INSERT 语句
INSERT INTO print_sink SELECT id, data, op_ts FROM mysql_source_target_table;
解释:
* 我们定义了表的结构,与MySQL中的 `target_table` 对应。`PRIMARY KEY (id) NOT ENFORCED` 是 CDC 源表需要的。
* `'hostname' = 'host.docker.internal'` 是关键,它让 Docker 内的 Flink 能够找到您宿主机上的 MySQL。
* `'scan.startup.mode' = 'initial'`:这样 Flink 会先读取 `target_table` 中已有的数据,然后再监听新的变化。
**第四步:进行测试**
现在,Flink 正在监听您的 `test_db.target_table`。让我们在 MySQL 中插入一些数据,看看 Flink 能否捕获到。- 在 MySQL 中向
target_table
插入数据:
USE test_db;
INSERT INTO target_table (id, data, op_ts) VALUES (1, 'Hello Flink from MySQL!', NOW(3));
-- 等待几秒钟
INSERT INTO target_table (id, data, op_ts) VALUES (2, 'Another record', NOW(3));
-- 等待几秒钟
UPDATE target_table SET data = 'Updated Hello Flink' WHERE id = 1;
-- 等待几秒钟
DELETE FROM target_table WHERE id = 2;
- 观察 Flink TaskManager 的日志:
print
connector 会将数据作为 INFO 级别的日志条目打印出来。
请执行以下命令来查看 TaskManager 的日志:
docker logs flink-taskmanager
在日志的最底下您应该能看到类似以下的输出 (格式可能略有不同):
如果您能看到这些输出,那么恭喜您!您已成功配置 Flink 通过 CDC 监测到了 MySQL 的数据变更。
- `+I` 表示插入 (INSERT)。
- `-U` 表示更新前的数据 (UPDATE_BEFORE),`+U` 表示更新后的数据 (UPDATE_AFTER)。
- `-D` 表示删除 (DELETE)。
最后附上这篇文章的语雀链接,直接从语雀里导出的,语雀里格式可能更规范一点(无广)
https://www.yuque.com/zhuiyue-w7umu/cqv2ol/gosr660bbyn6ez30
计划出一系列文章来介绍实现帖子搜索的业务和技术逻辑,这是第一篇