Flink实现基础地监听MySQL的CRUD操作

前言

声明:
本文主要文本内容由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` 格式。
  1. 修改 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] 配置段。
    • 添加或修改以下配置项:
[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` 文件。
  1. 重启 MySQL 服务
    • 打开 Windows 的 “服务” (Services)。可以按 Win + R,输入 services.msc 并回车。
    • 在服务列表中找到您的 MySQL 服务 (通常名为 “MySQL” 或类似 “MySQL80” 的名称)。
    • 右键点击该服务,选择 “重新启动”。
    • 其他方法可自己询问AI。
  2. 创建 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;
  1. 验证 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。
  1. 拉取 Flink 1.18.1 Docker 镜像
    打开 PowerShell 或命令提示符,执行:
docker pull flink:1.18.1-scala_2.12-java11

(我们选择带有 Scala 2.12 和 Java 11 的镜像,这是一个常用且稳定的组合)

  1. 启动 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。
  1. 启动 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 地址。
  1. 验证 Flink 集群是否运行
    • 打开浏览器,访问 http://localhost:8081。您应该能看到 Flink 的 Web UI。
    • 在 UI 中,检查 “Task Managers” 部分,应该能看到一个可用的 TaskManager。

  1. 进入 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
  1. 进入 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
  1. 重启 JobManager 和 TaskManager 容器
    为了确保 Flink 进程在启动时能加载新下载到 /opt/flink/lib 目录中的 JAR 文件,最稳妥的方式是重启容器。
docker restart flink-jobmanager
docker restart flink-taskmanager

等待几秒钟让它启动。

  1. 验证 TaskManager 的类路径(可选):
    等待 TaskManager 启动后,立即查看其最新的日志,并特别关注启动时打印的 Classpath 信息,确保 flink-sql-connector-mysql-cdc-3.0.1.jar 已经包含在内(可直接把日志丢给AI,让AI判断是否成功启动):
docker logs flink-taskmanager
**第三步:编写并执行 Flink SQL 作业**
现在我们将使用 Flink SQL 客户端来定义数据源 (MySQL) 和数据汇 (打印到控制台),并运行一个查询。
  1. 启动 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 客户端的路径。
  1. 在 Flink SQL 客户端中执行以下 DDL 和 DML 语句
    • 创建 MySQL CDC 源表 (mysql_source_target_table)
      将下面的 SQL 粘贴到 Flink SQL 客户端并执行。这条语句告诉 Flink如何连接到您的 MySQL 表并读取变更数据。
-- 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 能否捕获到。
  1. 在 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;
  1. 观察 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

计划出一系列文章来介绍实现帖子搜索的业务和技术逻辑,这是第一篇

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值