Flink1.18 同步 MySQL 到 Doris

一、前言

使用Apache Flink实现数据同步的ETL(抽取、转换、加载)过程通常涉及从源系统(如数据库、消息队列或文件)中抽取数据,进行必要的转换,然后将数据加载到目标系统(如另一个数据库或数据仓库)。在这里,我们将展示如何使用Apache Flink来实现一个从MySQL或Oracle数据库抽取数据并同步到另一个Doris数据库的ETL过程。

Flink官网: Apache Flink CDC | Apache Flink CDC

开启 Mysql Binlog

修改我们的配置文件**my.cnf**,增加:

XML 复制代码
server_id=1
log_bin=mysql-bin
binlog_format=ROW
expire_logs_days=30

重启 mysql

bash 复制代码
# 判断MySQL是否已经开启binlog   on  为打开状态
SHOW VARIABLES LIKE 'log_bin';    
 
# 查看MySQL的binlog模式
show global variables like "binlog%";
 
# 查看日志开启状态 
show variables like 'log_%';
 
# 刷新log日志,立刻产生一个新编号的binlog日志文件,跟重启一个效果 
flush logs;
 
# 清空所有binlog日志 
reset master;

1、下载 Flink 1.18.0,解压后得到 flink-1.18.0 目录。 使用下面的命令跳转至 Flink 目录下,并且设置 FLINK_HOME 为 flink-1.18.0 所在目录。

bash 复制代码
tar -xzf flink-*.tgz

cd flink-1.18.0

export FLINK_HOME=/usr/local/flink-1.18.0

2、通过在 conf/flink-conf.yaml 配置文件追加下列参数开启 checkpoint,每隔 3 秒做一次 checkpoint。

bash 复制代码
execution.checkpointing.interval: 3000

3、使用下面的命令启动 Flink 集群。

bash 复制代码
cd /usr/local/flink-1.18.0
./bin/start-cluster.sh

Flink现在作为后台进程运行。您可以使用以下命令检查其状态:

bash 复制代码
ps aux | grep flink

启动成功的话,可以在 http://localhost:8081/访问到 Flink Web UI,如下所示:

多次执行 start-cluster.sh 可以拉起多个 TaskManager。

如果想修改端口,可以在 conf/flink-conf.yaml 中修改 rest.port

要快速停止集群和所有正在运行的组件,您可以使用提供的脚本:

bash 复制代码
./bin/stop-cluster.sh

三、通过 FlinkCDC cli 提交任务

支持的连接器:

Connector Database Driver
mongodb-cdc * MongoDB: 3.6, 4.x, 5.0, 6.0, 6.1 MongoDB Driver: 4.9.1
mysql-cdc * MySQL: 5.6, 5.7, 8.0.x * RDS MySQL: 5.6, 5.7, 8.0.x * PolarDB MySQL: 5.6, 5.7, 8.0.x * Aurora MySQL: 5.6, 5.7, 8.0.x * MariaDB: 10.x * PolarDB X: 2.0.1 JDBC Driver: 8.0.28
oceanbase-cdc * OceanBase CE: 3.1.x, 4.x * OceanBase EE: 2.x, 3.x, 4.x OceanBase Driver: 2.4.x
oracle-cdc * Oracle: 11, 12, 19, 21 Oracle Driver: 19.3.0.0
postgres-cdc * PostgreSQL: 9.6, 10, 11, 12, 13, 14 JDBC Driver: 42.5.1
sqlserver-cdc * Sqlserver: 2012, 2014, 2016, 2017, 2019 JDBC Driver: 9.4.1.jre8
tidb-cdc * TiDB: 5.1.x, 5.2.x, 5.3.x, 5.4.x, 6.0.0 JDBC Driver: 8.0.27
db2-cdc * Db2: 11.5 Db2 Driver: 11.5.0.0
vitess-cdc * Vitess: 8.0.x, 9.0.x MySql JDBC Driver: 8.0.26

下表显示了Flink CDC连接器和Flink 之间的版本映射:

Flink® CDC Version Flink® Version
1.0.0 1.11.*
1.1.0 1.11.*
1.2.0 1.12.*
1.3.0 1.12.*
1.4.0 1.13.*
2.0.* 1.13.*
2.1.* 1.13.*
2.2.* 1.13.*, 1.14.*
2.3.* 1.13.*, 1.14.*, 1.15.*, 1.16.*
2.4.* 1.13.*, 1.14.*, 1.15.*, 1.16.*, 1.17.*
3.0.* 1.14.*, 1.15.*, 1.16.*, 1.17.*, 1.18.*

1、下载下面列出的二进制压缩包,并解压得到目录 flink-cdc-3.1.0flink-cdc-3.1.0-bin.tar.gz flink-cdc-3.1.0 下会包含 binliblogconf 四个目录。

2、下载下面列出的 connector 包,并且移动到 lib 目录下; 下载链接只对已发布的版本有效, SNAPSHOT 版本需要本地基于 master 或 release- 分支编译.

3、编写任务配置 yaml 文件 下面给出了一个整库同步的示例文件 mysql-to-doris.yaml

bash 复制代码
################################################################################
# Description: Sync MySQL all tables to Doris
################################################################################
source:
  type: mysql
  hostname: localhost
  port: 3306
  username: root
  password: 123456
  tables: app_db.\.*
  server-id: 5400-5404
  server-time-zone: UTC

sink:
  type: doris
  fenodes: 127.0.0.1:8030
  username: root
  password: ""
  table.create.properties.light_schema_change: true
  table.create.properties.replication_num: 1

pipeline:
  name: Sync MySQL Database to Doris
  parallelism: 2

其中: source 中的 tables: app_db.\.* 通过正则匹配同步 app_db 下的所有表。 sink 添加 table.create.properties.replication_num 参数是由于 Docker 镜像中只有一个 Doris BE 节点。

4、最后,通过命令行提交任务到 Flink Standalone cluster

bash 复制代码
bash bin/flink-cdc.sh mysql-to-doris.yaml

提交成功后,返回信息如:

bash 复制代码
Pipeline has been submitted to cluster.
Job ID: ae30f4580f1918bebf16752d4963dc54
Job Description: Sync MySQL Database to Doris

在 Flink Web UI,可以看到一个名为 Sync MySQL Database to Doris 的任务正在运行。

四、Route the changes

Flink CDC 提供了将源表的表结构/数据路由到其他表名的配置,借助这种能力,我们能够实现表名库名替换,整库同步等功能。 下面提供一个配置文件说明:

bash 复制代码
################################################################################
# Description: Sync MySQL all tables to Doris
################################################################################
source:
   type: mysql
   hostname: localhost
   port: 3306
   username: root
   password: 123456
   tables: app_db.\.*
   server-id: 5400-5404
   server-time-zone: UTC

sink:
   type: doris
   fenodes: 127.0.0.1:8030
   benodes: 127.0.0.1:8040
   username: root
   password: ""
   table.create.properties.light_schema_change: true
   table.create.properties.replication_num: 1

route:
   - source-table: app_db.orders
     sink-table: ods_db.ods_orders
   - source-table: app_db.shipments
     sink-table: ods_db.ods_shipments
   - source-table: app_db.products
     sink-table: ods_db.ods_products

pipeline:
   name: Sync MySQL Database to Doris
   parallelism: 2

通过上面的 route 配置,会将 app_db.orders 表的结构和数据同步到 ods_db.ods_orders 中。从而实现数据库迁移的功能。 特别地,source-table 支持正则表达式匹配多表,从而实现分库分表同步的功能,例如下面的配置:

bash 复制代码
route:
  - source-table: app_db.order\.*
    sink-table: ods_db.ods_orders

这样,就可以将诸如 app_db.order01app_db.order02app_db.order03 的表汇总到 ods_db.ods_orders 中。注意,目前还不支持多表中存在相同主键数据的场景,将在后续版本支持。

以下扩展笔记

使用下面的命令启动 Flink SQL CLI

bash 复制代码
#在flink目录下
./bin/sql-client.sh

然后建表语句创建Flink表 ,以下展示将flink_source.source_test表实时同步到flink_sink、flink_sink_second的sink_test表,Mysql同步Mysql。

bash 复制代码
# 每 3 秒做一次 checkpoint,用于测试,生产配置建议5到10分钟
Flink SQL> SET execution.checkpointing.interval = 3s;
[INFO] Session property has been set.

Flink SQL> CREATE TABLE source_test (
>   user_id STRING,
>   user_name STRING,
>   PRIMARY KEY (user_id) NOT ENFORCED
> ) WITH (
>    'connector' = 'mysql-cdc',
>    'hostname' = '192.168.3.31',
>    'port' = '3306',
>    'username' = 'root',
>    'password' = '******',
>    'database-name' = 'flink_source',
>    'table-name' = 'source_test'
> );
[INFO] Execute statement succeed.

Flink SQL> CREATE TABLE sink_test (
>   user_id STRING,
>   user_name STRING,
>   PRIMARY KEY (user_id) NOT ENFORCED
> ) WITH (
>    'connector' = 'jdbc',
>    'url' = 'jdbc:mysql://192.168.3.31:3306/flink_sink',
>    'driver' = 'com.mysql.cj.jdbc.Driver',
>    'username' = 'root',
>    'password' = '******',
>    'table-name' = 'sink_test'
> );
[INFO] Execute statement succeed.

Flink SQL> CREATE TABLE sink_test_second (
>   user_id STRING,
>   user_name STRING,
>   PRIMARY KEY (user_id) NOT ENFORCED
> ) WITH (
>    'connector' = 'jdbc',
>    'url' = 'jdbc:mysql://192.168.3.31:3306/flink_sink_second',
>    'driver' = 'com.mysql.cj.jdbc.Driver',
>    'username' = 'root',
>    'password' = '******',
>    'table-name' = 'sink_test'
> );
[INFO] Execute statement succeed.

Flink SQL> insert into sink_test select * from source_test;
[INFO] Submitting SQL update statement to the cluster...
[INFO] SQL update statement has been successfully submitted to the cluster:
Job ID: 0c49758cc251699f0b4acd6c9f735e6e


Flink SQL> insert into sink_test_second select * from source_test;
[INFO] Submitting SQL update statement to the cluster...
[INFO] SQL update statement has been successfully submitted to the cluster:
Job ID: ecea685a715d7d40ee1a94aac3236c18


Flink SQL> 

注意需要将flink-sql-connector-mysql-cdc-3.1.0.jar放到{flink-1.18.0}/lib/ 下 。

下载 Flink CDC 相关 Jar 包:Central Repository: com/ververica/flink-sql-connector-mysql-cdc

Mysql连接器选项:

Option Required Default Type Description
connector required (none) String 指定要使用的连接器, 这里应该是 'mysql-cdc'.
hostname required (none) String MySQL 数据库服务器的 IP 地址或主机名。
username required (none) String 连接到 MySQL 数据库服务器时要使用的 MySQL 用户的名称。
password required (none) String 连接 MySQL 数据库服务器时使用的密码。
database-name required (none) String 要监视的 MySQL 服务器的数据库名称。数据库名称还支持正则表达式,以监视多个与正则表达式匹配的表。
table-name required (none) String 需要监视的 MySQL 数据库的表名。表名支持正则表达式,以监视满足正则表达式的多个表。注意:MySQL CDC 连接器在正则匹配表名时,会把用户填写的 database-name, table-name 通过字符串 `\\.` 连接成一个全路径的正则表达式,然后使用该正则表达式和 MySQL 数据库中表的全限定名进行正则匹配。
port optional 3306 Integer MySQL 数据库服务器的整数端口号。
server-id optional (none) String 读取数据使用的 server id,server id 可以是个整数或者一个整数范围,比如 '5400' 或 '5400-5408', 建议在 'scan.incremental.snapshot.enabled' 参数为启用时,配置成整数范围。因为在当前 MySQL 集群中运行的所有 slave 节点,标记每个 salve 节点的 id 都必须是唯一的。 所以当连接器加入 MySQL 集群作为另一个 slave 节点(并且具有唯一 id 的情况下),它就可以读取 binlog。 默认情况下,连接器会在 5400 和 6400 之间生成一个随机数,但是我们建议用户明确指定 Server id。
scan.incremental.snapshot.enabled optional true Boolean 增量快照是一种读取表快照的新机制,与旧的快照机制相比, 增量快照有许多优点,包括: (1)在快照读取期间,Source 支持并发读取, (2)在快照读取期间,Source 支持进行 chunk 粒度的 checkpoint, (3)在快照读取之前,Source 不需要数据库锁权限。 如果希望 Source 并行运行,则每个并行 Readers 都应该具有唯一的 Server id,所以 Server id 必须是类似 `5400-6400` 的范围,并且该范围必须大于并行度。 请查阅 增量快照读取 章节了解更多详细信息。
scan.incremental.snapshot.chunk.size optional 8096 Integer 表快照的块大小(行数),读取表的快照时,捕获的表被拆分为多个块。
scan.snapshot.fetch.size optional 1024 Integer 读取表快照时每次读取数据的最大条数。
scan.startup.mode optional initial String MySQL CDC 消费者可选的启动模式, 合法的模式为 "initial","earliest-offset","latest-offset","specific-offset" 和 "timestamp"。 请查阅 启动模式 章节了解更多详细信息。
scan.startup.specific-offset.file optional (none) String 在 "specific-offset" 启动模式下,启动位点的 binlog 文件名。
scan.startup.specific-offset.pos optional (none) Long 在 "specific-offset" 启动模式下,启动位点的 binlog 文件位置。
scan.startup.specific-offset.gtid-set optional (none) String 在 "specific-offset" 启动模式下,启动位点的 GTID 集合。
scan.startup.specific-offset.skip-events optional (none) Long 在指定的启动位点后需要跳过的事件数量。
scan.startup.specific-offset.skip-rows optional (none) Long 在指定的启动位点后需要跳过的数据行数量。
server-time-zone optional (none) String 数据库服务器中的会话时区, 例如: "Asia/Shanghai". 它控制 MYSQL 中的时间戳类型如何转换为字符串。 更多请参考 这里. 如果没有设置,则使用ZoneId.systemDefault()来确定服务器时区。
debezium.min.row. count.to.stream.result optional 1000 Integer 在快照操作期间,连接器将查询每个包含的表,以生成该表中所有行的读取事件。 此参数确定 MySQL 连接是否将表的所有结果拉入内存(速度很快,但需要大量内存), 或者结果是否需要流式传输(传输速度可能较慢,但适用于非常大的表)。 该值指定了在连接器对结果进行流式处理之前,表必须包含的最小行数,默认值为1000。将此参数设置为`0`以跳过所有表大小检查,并始终在快照期间对所有结果进行流式处理。
connect.timeout optional 30s Duration 连接器在尝试连接到 MySQL 数据库服务器后超时前应等待的最长时间。
connect.max-retries optional 3 Integer 连接器应重试以建立 MySQL 数据库服务器连接的最大重试次数。
connection.pool.size optional 20 Integer 连接池大小。
jdbc.properties.* optional 20 String 传递自定义 JDBC URL 属性的选项。用户可以传递自定义属性,如 'jdbc.properties.useSSL' = 'false'.
heartbeat.interval optional 30s Duration 用于跟踪最新可用 binlog 偏移的发送心跳事件的间隔。
debezium.* optional (none) String 将 Debezium 的属性传递给 Debezium 嵌入式引擎,该引擎用于从 MySQL 服务器捕获数据更改。 For example: 'debezium.snapshot.mode' = 'never'. 查看更多关于 Debezium 的 MySQL 连接器属性
scan.incremental.close-idle-reader.enabled optional false Boolean 是否在快照结束后关闭空闲的 Reader。 此特性需要 flink 版本大于等于 1.14 并且 'execution.checkpointing.checkpoints-after-tasks-finish.enabled' 需要设置为 true。

六、使用数据流API

包含以下Maven依赖项(通过Maven中心库提供):

XML 复制代码
<dependency>
  <groupId>org.apache.flink</groupId>
  <!-- 添加与你的数据库匹配的依赖 -->
  <artifactId>flink-connector-mysql-cdc</artifactId>
  <!-- 该依赖仅适用于稳定发布,SNAPSHOT依赖需要根据master或release分支自行构建。 -->
  <version>3.1.0</version>
</dependency>
java 复制代码
import org.apache.flink.api.common.eventtime.WatermarkStrategy;
import org.apache.flink.streaming.api.environment.StreamExecutionEnvironment;
import org.apache.flink.cdc.debezium.JsonDebeziumDeserializationSchema;
import org.apache.flink.cdc.connectors.mysql.source.MySqlSource;

public class MySqlSourceExample {
  public static void main(String[] args) throws Exception {
    MySqlSource<String> mySqlSource = MySqlSource.<String>builder()
            .hostname("yourHostname")
            .port(yourPort)
            .databaseList("yourDatabaseName") // 设置捕获的数据库
            .tableList("yourDatabaseName.yourTableName") // 设置捕获的表
            .username("yourUsername")
            .password("yourPassword")
            .deserializer(new JsonDebeziumDeserializationSchema()) // 将SourceRecord转换为JSON字符串
            .build();

    StreamExecutionEnvironment env = StreamExecutionEnvironment.getExecutionEnvironment();

    // 启用检查点
    env.enableCheckpointing(3000);

    env
      .fromSource(mySqlSource, WatermarkStrategy.noWatermarks(), "MySQL Source")
      // 设置4个并行源任务
      .setParallelism(4)
      .print().setParallelism(1); // 为sink设置并行度为1,以保持消息顺序

    env.execute("Print MySQL Snapshot + Binlog");
  }
}
相关推荐
Edingbrugh.南空14 小时前
Flink ClickHouse 连接器维表源码深度解析
java·clickhouse·flink
诗旸的技术记录与分享1 天前
Flink-1.19.0源码详解-番外补充3-StreamGraph图
大数据·flink
Edingbrugh.南空1 天前
Flink MySQL CDC 环境配置与验证
mysql·adb·flink
bxlj_jcj2 天前
深入Flink核心概念:解锁大数据流处理的奥秘
大数据·flink
Edingbrugh.南空2 天前
Flink SQLServer CDC 环境配置与验证
数据库·sqlserver·flink
Edingbrugh.南空2 天前
Flink OceanBase CDC 环境配置与验证
大数据·flink·oceanbase
Edingbrugh.南空3 天前
Flink TiDB CDC 环境配置与验证
大数据·flink·tidb
Edingbrugh.南空3 天前
Flink Postgres CDC 环境配置与验证
大数据·flink
lifallen3 天前
Paimon vs. HBase:全链路开销对比
java·大数据·数据结构·数据库·算法·flink·hbase
expect7g13 天前
新时代多流Join的一个思路----Partial Update
后端·flink