创建-01、Flink CDC达成MySQL数据动态监控

1. 常见开源 CDC 方案比较

在这里插入图片描述

2. Flink CDC 介绍

Flink CDC 是 Apache Flink 中一个功能强大的组件,用于实时捕获和处理数据库中的数据变更。可以实时地从各种数据库(如SQL Server、MySQL、PostgreSQL、Oracle、MongoDB等等)中捕获数据变更并将其转换为流式数据。

FlinkCDC 同步数据有两种方式:

  • FlinkSQL
  • Flink DataStream 和 Table API(本文用这种)

3. 实现

环境要求

  • jdk 17
  • MySQL 8.0 +
  • flink-1.20.3(只是相关 jar 包,不需要安装 flink)
  • flink-cdc-3.5.0(只是相关 jar 包,不需要安装 flink)

实现模式

  • 本地模式(本文用这种):无需连接外部 Flink 集群,在 IDE(如 IDEA/Eclipse)中运行 main 方法时,Flink 会自动启动一个嵌入式的本地集群(包含一个 JobManager 和一个 TaskManager,运行在当前 JVM 进程中),代码会直接在这个本地集群中执行。
  • 集群模式:必须连接已安装的 Flink 集群,当代码开发完成后,需要将其打包成 JAR 文件,提交到独立部署的 Flink 集群(包含 JobManager 和 TaskManager 进程,可能分布在多台机器)中运行。此时,代码需要通过 Flink 集群的地址(如JobManager的 IP: 端口)与集群通信,由集群分配资源并执行作业。

实现步骤

  1. 数据准备

    • 在MySQL数据库test中创建一个数据表user

      CREATE TABLE `user` (
      `id` int NOT NULL,
      `name` varchar(100) COLLATE utf8mb4_general_ci DEFAULT NULL,
      `age` int DEFAULT NULL,
      PRIMARY KEY (`id`)
      ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci;
    • 确认MySQL的Binlog已经开启并且格式是ROW且时区正确
      在这里插入图片描述
      在这里插入图片描述
      在这里插入图片描述

  2. 自行通过 IDE(如 IDEA/Eclipse)创建一个 Maven 项目

  3. pom 中引入如下 jar 包

    <properties>
    <maven.compiler.source>17</maven.compiler.source>
    <maven.compiler.target>17</maven.compiler.target>
    <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
    <flink.version>1.20.3</flink.version>
    <flink-cdc.version>3.5.0</flink-cdc.version>
    </properties>
    <dependencies>
      <!-- Flink connector连接器基础包 -->
        <dependency>
        <groupId>org.apache.flink</groupId>
        <artifactId>flink-connector-base</artifactId>
        <version>${flink.version}</version>
        </dependency>
        <!-- Flink CDC MySQL源 -->
          <dependency>
          <groupId>org.apache.flink</groupId>
          <artifactId>flink-sql-connector-mysql-cdc</artifactId>
          <version>${flink-cdc.version}</version>
          </dependency>
          <!-- Flink DataStream数据流API -->
            <dependency>
            <groupId>org.apache.flink</groupId>
            <artifactId>flink-connector-mysql-cdc</artifactId>
            <version>${flink-cdc.version}</version>
            <scope>provided</scope>
            </dependency>
            <!-- Flink客户端-->
              <dependency>
              <groupId>org.apache.flink</groupId>
              <artifactId>flink-clients</artifactId>
              <version>${flink.version}</version>
              </dependency>
              <!--Flink WebUI,端口8081(默认没有开启)-->
                <dependency>
                <groupId>org.apache.flink</groupId>
                <artifactId>flink-runtime-web</artifactId>
                <version>${flink.version}</version>
                </dependency>
                <!--Flink Table API&SQL程序可以连接到其他外部系统,用于读写批处理表和流式表。-->
                <dependency>
                <groupId>org.apache.flink</groupId>
                <artifactId>flink-table-runtime</artifactId>
                <version>${flink.version}</version>
                </dependency>
                <!-- MySQL 驱动 -->
                  <dependency>
                  <groupId>mysql</groupId>
                  <artifactId>mysql-connector-java</artifactId>
                  <version>8.0.28</version>
                  </dependency>
                </dependencies>
  4. main 方法

    public static void main(String[] args) {
    // 配置监听数据源
    MySqlSource<String> source = MySqlSource.<String>builder()
      // mysql ip
      .hostname("ip")
      .port(3306)
      // 数据库集合,可以配置多个
      .databaseList("test")
      // 表集合,可以配置多个
      .tableList("test.user")
      .username("root")
      .password("123456")
      .serverTimeZone("Asia/Shanghai")
      .deserializer(new JsonDebeziumDeserializationSchema())
      .includeSchemaChanges(true)
      .build();
      // 生成本地的 Flink WebUI,启动成功后可以通过 http://localhost:8081 访问
      Configuration configuration = new Configuration();
      configuration.set(RestOptions.BIND_PORT, "8081");
      StreamExecutionEnvironment env = StreamExecutionEnvironment.getExecutionEnvironment(configuration);
      // checkpoint 的侧重点是“容错”,即 Flink 作业意外失败并重启之后,能够直接从早先打下的 checkpoint 恢复运行,且不影响作业逻辑的准确性。
      env.enableCheckpointing(5000);
      DataStreamSource<String> cdcStream = env.fromSource(source, WatermarkStrategy.noWatermarks(), "MySQL Source");
        SingleOutputStreamOperator<String> streamOperator = cdcStream.map(jsonStr -> {
          return jsonStr;
          })
          .filter(Objects::nonNull)  // 过滤空值
          .name("解析CDC事件并提取业务数据");
          // 输出结果
          streamOperator.print();
          // 执行作业
          env.execute();
          }
  5. 启动执行main方法一定要加上以下JVM参数

    由于Java 17 的模块系统限制。从 Java 9 开始引入的模块系统默认不允许访问非公开的内部 API,而 ArraysAsListSerializer 尝试通过反射访问 Arrays.ArrayList 的私有字段,这在较新的 Java 版本中被禁止。所以要配置以下的参数打开必要的模块访问权限。

    --add-opens java.base/java.util=ALL-UNNAMED
    --add-opens java.base/java.lang=ALL-UNNAMED
  6. 访问 http://localhost:8081 可以看到有一个正在运行的 job
    在这里插入图片描述

  7. 修改test.user表的数据,zhangsan的age从25改成26

  8. IDE 控制台会输出:

    {
    "before":{"id":1,"name":"zhangsan","age":25},
    "after":{"id":1,"name":"zhangsan","age":26},
    "source":{
    "version":"1.9.8.Final",
    "connector":"mysql",
    "name":"mysql_binlog_source",
    "ts_ms":1762420693000,
    "snapshot":"false",
    "db":"test",
    "sequence":null,
    "table":"user",
    "server_id":3306,
    "gtid":null,
    "file":"mysql-bin.000010",
    "pos":295736734,
    "row":0,
    "thread":894394,
    "query":null
    },
    "op":"u",
    "ts_ms":1762420719283,
    "transaction":null}
posted @ 2026-02-10 15:02  clnchanpin  阅读(46)  评论(0)    收藏  举报