详述Flink SQL Connector写入clickhouse的问题与方法

笔者使用Flink SQL(jdbc connector)将实时数据写入Clickhouse时,查询Flink官方文档发现flink-connector-jdbc仅支持MySQL,PostgreSQL和Derby。无奈只能上手查阅资料,并扩展源码功能解决。

注:1.11.0版本之后flink-connector-jdbc DataStream支持了ClickHouse Sink

1. 解决办法

1.1 扩展flink-connector-jdbc支持clickhouse

github上下载flink项目源码:https://github.com/apache/flink.git

下载的flink源码整个项目比较难一次编译成功,这里提供两个快速解决办法,以供参考:

  • 将阿里云仓库镜像放入本地maven settings.xml的中(放在mirrors标签里第一个)
<mirror>
   <id>nexus-aliyun</id>
    <mirrorOf>*,!jeecg,!jeecg-snapshots,!mapr-releases</mirrorOf>
    <name>Nexus aliyun</name>
   <url>http://maven.aliyun.com/nexus/content/groups/public</url>
</mirror>
 
<mirror>
    <id>mapr-public</id>
    <mirrorOf>mapr-releases</mirrorOf>
    <name>mapr-releases</name>
   <url>https://maven.aliyun.com/repository/mapr-public</url>
</mirror>
  • 将flink-connector-jdbc子项目中的flink版本改为已发布的稳定版本号(例:1.12.0),就可以仅打包这个子项目。

仿照flink-connector-jdbc支持mysql的情况添加Clickhouse相关代码,共需添加三处:ClickHouseDialectClickHouseRowConverter,修改JdbcDialects添加ClickHouseDialect()。话不多说,上代码。

  • org.apache.flink.connector.jdbc.dialect.ClickHouseDialect
package org.apache.flink.connector.jdbc.dialect;

import org.apache.flink.connector.jdbc.internal.converter.ClickHouseRowConverter;
import org.apache.flink.connector.jdbc.internal.converter.JdbcRowConverter;
import org.apache.flink.table.types.logical.LogicalTypeRoot;
import org.apache.flink.table.types.logical.RowType;

import java.util.Arrays;
import java.util.List;
import java.util.Optional;

/** JDBC dialect for ClickHouse. */
public class ClickHouseDialect extends AbstractDialect {

   private static final long serialVersionUID = 1L;

   private static final String SQL_DEFAULT_PLACEHOLDER = " :";
   private static final int MAX_TIMESTAMP_PRECISION = 6;
   private static final int MIN_TIMESTAMP_PRECISION = 1;
   private static final int MAX_DECIMAL_PRECISION = 65;
   private static final int MIN_DECIMAL_PRECISION = 1;

   @Override
   public boolean canHandle(String url) {
       return url.startsWith("jdbc:clickhouse:");
   }

   @Override
   public JdbcRowConverter getRowConverter(
           RowType rowType) {
       return new ClickHouseRowConverter(rowType);
   }

   @Override
   public Optional<String> defaultDriverName() {
       return Optional.of("ru.yandex.clickhouse.ClickHouseDriver");
   }

   @Override
   public String quoteIdentifier(String identifier) {
       return identifier;
   }

   @Override
   public int maxDecimalPrecision() {
       return MAX_DECIMAL_PRECISION;
   }

   @Override
   public int minDecimalPrecision() {
       return MIN_DECIMAL_PRECISION;
   }

   @Override
   public int maxTimestampPrecision() {
       return MAX_TIMESTAMP_PRECISION;
   }

   @Override
   public int minTimestampPrecision() {
       return MIN_TIMESTAMP_PRECISION;
   }

   @Override
   public List<LogicalTypeRoot> unsupportedTypes() {
       return Arrays.asList(
               LogicalTypeRoot.BINARY,
               LogicalTypeRoot.TIMESTAMP_WITH_LOCAL_TIME_ZONE,
               LogicalTypeRoot.TIMESTAMP_WITH_TIME_ZONE,
               LogicalTypeRoot.INTERVAL_YEAR_MONTH,
               LogicalTypeRoot.INTERVAL_DAY_TIME,
               LogicalTypeRoot.ARRAY,
               LogicalTypeRoot.MULTISET,
               LogicalTypeRoot.MAP,
               LogicalTypeRoot.ROW,
               LogicalTypeRoot.DISTINCT_TYPE,
               LogicalTypeRoot.STRUCTURED_TYPE,
               LogicalTypeRoot.NULL,
               LogicalTypeRoot.RAW,
               LogicalTypeRoot.SYMBOL,
               LogicalTypeRoot.UNRESOLVED
       );
   }

   @Override
   public String dialectName() {
       return "ClickHouse";
   }

}

  • org.apache.flink.connector.jdbc.internal.converter.ClickHouseRowConverter
package org.apache.flink.connector.jdbc.internal.converter;

import org.apache.flink.table.types.logical.RowType;

/**
 * Runtime converter that responsible to convert between JDBC object and Flink internal object for
 * ClickHouse.
 */
public class ClickHouseRowConverter extends AbstractJdbcRowConverter {

    private static final long serialVersionUID = 1L;

    @Override
    public String converterName() {
        return "ClickHouse";
    }

    public ClickHouseRowConverter(RowType rowType) {
        super(rowType);
    }
}

org.apache.flink.connector.jdbc.dialect.JdbcDialects

public final class JdbcDialects {

    private static final List<JdbcDialect> DIALECTS = Arrays.asList(
            new DerbyDialect(),
            new MySQLDialect(),
            new PostgresDialect(),
            new ClickHouseDialect(), //这里是上面的ClickHouseDialect的类对象
            new OracleDialect()
    );
    ......
    ......
}

其它支持JDBC的数据源也可使用此方法继续扩展,比如笔者这里的OracleDialect()。

1.2 使用flink-connector-clickhouse

该方法阿里云文档 “ 使用flink-connector-clickhouse写入ClickHouse ” 中有详细描述,可自行查阅。

注:该connector从Flink 1.12版本开始支持,Flink1.11使用会报错。且该插件maven依赖下载和安装会出问题,可直接下载jar包导入项目Libraries中。或者在github上有相关代码,这里就自行寻找不贴链接了。

2. Flink SQL读写Clickhouse示例

2.1 flink-connector-jdbc使用

CREATE TABLE test_rightTable (
  id INT,
  name STRING,
  gender STRING,
  age INT,
  address STRING,
  phone INT
) WITH (
  'connector' = 'jdbc',
  'url' = 'jdbc:clickhouse://*****:8123/default',
  'username' = 'default',
  'password' = '******',
  'table-name' = 'test_rightTable'
);

2.2 flink-connector-clickhouse使用

CREATE TABLE test_sink_clickhouse_table 
   logtime STRING,
   col1 STRING,
   col2 STRING
 ) WITH (
   'connector' = 'clickhouse',
   'url' = 'clickhouse://****:8124', //clickhouse的host:port
   'table-name' = 'test_sink_clickhouse_table'
)

完整SQL程序可参考Flink 1.11 SQL 快速上手,内含Demo及详细分析和使用过程,亲测可行!

3. 其它问题及注意事项

① ClickHouse数据抽取问题

flink-connector-clickhouse只支持加载,不支持抽取,扩展的flink-connector-jdbc是都支持的。

② 库名指定问题

配置url的时候使用clickhouse://****:8124/${database-name}并不会直接报错,但这里的库名指定是不生效的,如果库名不是default,且报错该表在default下不存在,需要另外使用database-name参数指定。

  • 2
    点赞
  • 20
    收藏
    觉得还不错? 一键收藏
  • 14
    评论
### 回答1: 你可以使用Flink Clickhouse Sink来将数据写入Clickhouse,具体步骤如下: 1. 安装Flink Clickhouse Sink:将Maven依赖添加到pom.xml文件中,并在Flink程序中添加依赖; 2. 创建Clickhouse数据库和表:使用ClickhouseSQL语句创建数据库和表; 3. 配置Flink Clickhouse Sink:使用ClickhouseSinkBuilder类来构建Flink Clickhouse Sink; 4. 将Flink Clickhouse Sink添加到Flink程序中:在Flink程序中添加Flink Clickhouse Sink,将流数据写入Clickhouse。 ### 回答2: 要将Flink SQL写入ClickHouse,可以按照以下步骤进行操作: 1. 首先,确保你已经正确配置好FlinkClickHouse的环境。 2. 在Flink SQL中,你需要创建一个Table,并定义它的结构、格式和连接器。例如,可以使用以下语句创建一个ClickHouse的Table: ``` CREATE TABLE clickhouse_table ( id INT, name STRING, age INT ) WITH ( 'connector' = 'clickhouse', 'url' = 'jdbc:clickhouse://localhost:8123/default', 'table-name' = 'clickhouse_table', 'username' = 'your_username', 'password' = 'your_password' ) ``` 这里的`'connector'`参数指定使用ClickHouse连接器,`'url'`参数指定ClickHouse的连接地址,`'table-name'`参数指定要写入ClickHouse表的名称,`'username'`和`'password'`参数用于验证。 3. 接下来,在你的Flink SQL作业中,使用类似以下的语句将数据写入ClickHouse: ``` INSERT INTO clickhouse_table SELECT id, name, age FROM source_table ``` 这里的`clickhouse_table`是在第2步中定义的ClickHouse表,`source_table`是源数据的表。 4. 最后,启动或提交Flink SQL作业,Flink将会将从源表中读取的数据写入ClickHouse表中。 需要注意的是,以上仅是一个基本的示例,实际场景下可能会有更多配置项和细节需要处理。优化性能和数据写入方式的问题也应根据具体情况进行考虑和调整。 ### 回答3: 要将Flink SQL写入ClickHouse,可以按以下步骤操作: 1. 配置ClickHouse连接:在Flink的配置文件中,将ClickHouse的连接信息添加到"flink-conf.yaml"文件中。包括ClickHouse的IP地址、端口号、用户名和密码等信息。 2. 创建ClickHouse表:在ClickHouse中创建一个用于接收Flink SQL结果的表。可以使用ClickHouse的客户端工具或通过在ClickHouse的管理界面执行SQL语句来完成表的创建。 3. 在Flink SQL中定义输出表:在Flink SQL中使用"CREATE TABLE"语句定义一个输出表,该表将用于将数据写入ClickHouse中。在表的定义中,需要指定表的名称、字段列表和数据类型,以及指定数据写入的目标表名。 4. 在Flink作业中配置ClickHouse写入器:在Flink的代码中,通过创建一个新的ClickHouseSinkFunction实例来配置ClickHouse写入器。将该写入器与Flink SQL中定义的输出表相关联,并将ClickHouse连接的配置信息传递给写入器。 5. 执行Flink作业:启动Flink作业并提交Flink SQL查询。Flink将根据查询结果将数据写入ClickHouse中的指定表中。 需要注意的是,FlinkClickHouse的版本兼容性,以及Flink SQLClickHouse的支持情况。在配置过程中,要确保FlinkClickHouse版本匹配,并且所使用的Flink SQL函数和语法在ClickHouse中被支持。 以上就是将Flink SQL写入ClickHouse的基本步骤,具体的实现方式可以根据具体情况进行调整和优化。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 14
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值