1.阿里云flink&selectdb-sql作业

1.概述

本文介绍使用阿里云实时计算flink把数据从自建mysql同步到阿里云selectdb的过程。本节是使用sql作业,后面会介绍使用jar作业,实践证明还是jar作业更强大,更灵活;
阿里云flink和selectdb的集成度比较差,遇到了不少的坑(主要是因为flink和开源版flink有差异,selectdb和doris也有差异)。强烈建议新入坑的同学不要采用此组合。如果预算够,并且想使用阿里云服务,建议采用flink+hologres;

2.目标

把自建mysql的约100张表准实时同步到云服务selectdb。数据量不大,约5个G左右;

源表flink结果表
自建mysql实时计算flink云服务selectdb

3.步骤(重点)

对问题和过程没兴趣的同学,可以直接看这里。本章节记录了阿里云flink与selectdb集成时,使用sql作业不写代码最简单的方式;

3.1.创建结果表

在selectdb创建结果表,注意结果表selectdb的varchar字段需要设置成源表mysql的varchar字段长度 * 3;

3.2.创建catalog

  • 使用flink默认提供的mysql元数据创建源表的catalog;
  • 创建自定义doris的catalog,然后创建结果表的catalog;
    注意直接下载的包是有问题的,需要进行一些修改;selecedb使用doris的catalog?
--创建doris元数据的语句&参数
CREATE CATALOG `dwdoris` 
WITH (
    'type' = 'doris' -- required
    --必传参数,格式为:database.table
    ,'table.identifier' = 'test.flink_test'
    ,'password' = 'test' -- required
    ,'jdbc-url' = 'jdbc:mysql://test.selectdbfe.rds.aliyuncs.com:9030' -- required
    ,'fenodes' = 'test.selectdbfe.rds.aliyuncs.com:8080'
    ,'username' = 'test' -- required
    ,'default-database' = 'test'
    ,'sink.enable-delete' = 'true'
    --在结果表selectdb使用json格式导入数据
    ,'sink.properties.format' = 'json'
);

3.3.创建sql作业

--********************************************************************--
-- Author:         Pings
-- Created Time:   2024-09-01
-- Description:    同步mysql作业
--                 添加运行参数,指定连接池数量
--                 当作业中包含多个mysql cdc源表,且不是使用ctas语句同步时,数据源无法进行复用,需要为每一个cdc源表提供不同的server-id
--********************************************************************--
begin statement set;
    --销售-PO
    insert into dwdoris.test.sale_po select * from mysql.test.sale_po /*+ OPTIONS('server-id'='3400','connection.pool.size' = '110') */;
    insert into dwdoris.test.sale_po_extend select * from mysql.test.sale_po_extend /*+ OPTIONS('server-id'='3401','connection.pool.size' = '110') */;
    insert into dwdoris.test.sale_po_item select * from mysql.test.sale_po_item /*+ OPTIONS('server-id'='3402','connection.pool.size' = '110') */;
    insert into dwdoris.test.sale_ddp_po_item_coupon select * from mysql.test.sale_ddp_po_item_coupon /*+ OPTIONS('server-id'='3403','connection.pool.size' = '110') */;
    insert into dwdoris.test.sale_ddp_po_item_extend select * from mysql.test.sale_ddp_po_item_extend /*+ OPTIONS('server-id'='3404','connection.pool.size' = '110') */;
    
    ...省略100条语句...
end;

3.4.运行sql作业

  • 如果作业启动不了,可以查看错误日志进行排查;
  • 默认同步每批数据的间隔为180秒,所以数据同步会有延迟;
    flink运行日志

4.过程&坑

4.1.整库同步

首先想的肯定是整库同步;

  • 首先想到使用flink cdc任务,把mysql整库同步到selectdb。并且支持后续mysql的ddl语句自动同步。结果发现阿里云flink不支持创建flink cdc任务;
  • 然后在阿里云flink找到CREATE DATABASE AS(CDAS)语句,能达到和flink cdc任务相同和效果。结果发现不支持selectdb做为结果表;
    flink-cdas支持的结果表
  • 尝试使用mysql和doris的catalog(cads语句需使用到catalog)。报错catalog必须实现CatalogTableProvide接口,提了工单也无法解决;

4.2.create+insert单表同步

整库同步行不通,只能单个表同步了;

  • 在selectdb创建结果表;
  • 创建flink sql作业;
    • 创建mysql源表和selectdb结果表的flink映射表;
    • 编写insert into语句同步表数据;
      CREATE TEMPORARY TABLE flink_test (
        id int NOT NULL,
        code varchar(50),
        PRIMARY KEY (id) NOT ENFORCED
      ) WITH (
          'connector' = 'mysql-cdc',
          'hostname' = '127.0.0.1',
          'port' = '3306',
          'username' = 'test',
          'password' = 'test',
          'database-name' = 'test',
          'table-name' = 'flink_test'
      );
      --selecedb目标表
      CREATE TEMPORARY TABLE flink_test_sink (
         id int NOT NULL,
         code varchar(50),
         PRIMARY KEY (`id`)  NOT ENFORCED
      ) WITH (
          'connector' = 'doris',
          'fenodes' = 'test.selectdbfe.rds.aliyuncs.com:8080',
          'table.identifier' = 'test.flink_test',
          'username' = 'test',
          'password' = 'test',
          'sink.enable-delete' = 'true'
      );
      insert into flink_test_sink select * from flink_test;
      

问题

selecedb的sink表应该采用什么连接器?
  • 使用selectdb连接器。需创建自定义connector,并上传jar(flink-selectdb-connector-1.17-2.1.1.jar);
    不兼容,报sql语法错误。错误信息忘记录了;
  • 使用mysql的连接器。默认已提供。原因是selectdb基于doris,兼容mysql;
    同步效率比较差,同步数据很慢;
    只支持insert和delete数据。修改数据时使用mysql的insert into … on duplicate key update语句,selectdb不支持报sql语法错误;
  • 使用doris连接器。需创建自定义connector,并上传jar(flink-doris-connector-1.17-1.6.2.jar);
    可以使用,同步数据比较使用用mysql的连接器快很多;
工作量太大,添加表/修改表结构非常麻烦
  • 需先在selectdb创建表,可以同步数据,但是数据结构不能同步;
  • 源表添加新字段后。需在flink的源表的结果表添加,然后在selectdb添加。如果不添加,结果表不会同步新字段,但数据可以继续同步;

4.3.catalog+insert单表同步

上个方法过于麻烦,查询资料发现可以使用catalog(元数据)管理。可以省略在flink作业中创建源表和结果表的工作;

  • 在selectdb创建结果表;
  • 创建mysql源表的catalog,命名为mysqluat;
  • 创建selectdb结果表的catalog,命名为dwdoris;
  • 创建flink sql作业,编写insert into语句同步表数据;
begin statement set;
    --通过catalog.database.table的方式访问表
    insert into dwdoris.test.flink_test select * from mysqluat.test.flink_test;
end;

问题

selecedb使用mysql的catalog?
  • 直接使用flink默认提供的mysql元数据,创建元数据成功。可以查询表和表结构;
  • 同步数据。编写insert into语句后,运行也是成功的;
    同步效率比较差,同步数据很慢;
    无法识别到selectdb的主键,导致只能同步insert和delete,不能进行update操作;
selecedb使用doris的catalog?

前面已经知道阿里云selecedb不兼容flink-selecedb相关的jar包。这里直接查找doris的包;

  • 使用doris元数据。需创建自定义catalog,并上传jar(flink-doris-connector-1.17-1.6.2.jar)。然后创建doris元数据;
--创建doris元数据的语句&参数
CREATE CATALOG `dwdoris` 
WITH (
    'type' = 'doris' -- required
    ,'table.identifier' = 'test.flink_test'
    ,'password' = 'test' -- required
    ,'jdbc-url' = 'jdbc:mysql://test.selectdbfe.rds.aliyuncs.com:9030' -- required
    ,'fenodes' = 'test.selectdbfe.rds.aliyuncs.com:8080'
    ,'username' = 'test' -- required
    ,'default-database' = 'test'
    ,'sink.enable-delete' = 'true'
);

报错缺少mysql的jdbc驱动。下载源码后把mysql的jdbc驱动打包进去,创建doris的catalog成功。可以查询表和表结构;

  • 同步数据。编写insert into语句后,运行报如下错误;

    No Doris FE is available, please check configuration or cluster status.

    说明: selectdb集群分为FE和BE;
    FE(Frontend)负责存储,维护集群的元数据信息;
    BE(Backend)负责存储物理数据;

查看源代码,发现需要访问http://test.selectdbfe.rds.aliyuncs.com:8080验证fe是否运行。然后提工单,客服说阿里云selectdb没有此链接。于是修改源码(BackendUtil.tryHttpConnection),屏蔽此链接的验证功能。注意后续还有获取BE也会验证此链接。重新操作后同步数据成功;
查看源代码,还发现需要访问http://test.selectdbfe.rds.aliyuncs.com:8080/api/database/table/_schema验证,所以table.identifier也必须要设置;

4.4.其它问题

actual column number in csv file is less then schema column number.actual: 23, schema column number: 45; line delimiter:

原因: 默认是通过csv文件的格式导入数据。当源表的数据中有换行符时,会判定为新的数据行。导致把一条数据识别成多条数据;
解决: 使用json格式导入数据;

--在结果表selectdb的catalog中修改参数,使用json格式导入数据
'sink.properties.format' = 'json'

selectdb的varchar和mysql的varchar占用的长度不一致;

在doris中,字符串是以UTF-8编码存储的,所以英文字符占1个字节,中文字符占3个字节。所以mysql的varchar长度在doris中最好统一乘3;

一个作业中insert语句超过20个时,作业无法启用;

    Caused by: java.util.concurrent.ExecutionException: java.util.concurrent.TimeoutException: 
    Invocation of [LocalRpcInvocation(RestfulGateway.requestJobStatus(JobID, Time))] at recipient
    [akka.tcp://flink@21.224.35.218:6123/user/rpc/dispatcher_1] timed out. This is usually caused by: 
    1) Akka failed sending the message silently, due to problems like oversized payload or serialization failures. In that case, you should find detailed error information in the logs. 
    2) The recipient needs more time for responding, due to problems like slow machines or network jitters. In that case, you can try to increase akka.ask.timeout.

按提示修改akka.ask.timeout为300s后,仍然报错;
原因: flink cdc mysql默认连接池为20(connection.pool.size),当任务超过20个时,无法获取到mysql连接;
解决: 增加连接池数量。经测试在mysql源表的catalog中添加connection.pool.size参数无效;

--添加运行参数,指定连接池数量
--当作业中包含多个mysql cdc源表,且不是使用ctas语句同步时,数据源无法进行复用,需要为每一个cdc源表提供不同的server-id
insert into dwdoris.test.flink_test select * from mysqluat.test.flink_test
/*+ OPTIONS('server-id'='3380', 'connection.pool.size' = '50') */;
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值