Flink的Sink支持mysql和Clickhouse

本文描述了作者在将Flink数据流直接写入Clickhouse时,从Kafka和开源Flink-Sink-Clickhouse遇到的问题,最终通过使用ApacheFlink官方的JDBC驱动,实现了低延迟且稳定的批量导入策略,分享了解决方案和代码实例。
摘要由CSDN通过智能技术生成

最近遇到一个问题需要把flink的数据直接输入到Clickhouse中,一开始直接输入到kafka然后通过视图去监听topic在入库,但是中间延迟严重以及会丢数据的情况,所以引入需要直接输入到Clickhouse库中。当前项目中有基于jdbc的还有基于中间件模式的,具体中间件模式的使用可以查看站内链接的博客。

一开始确实引入了很多 开源的flink-sink-Clickhouse的包但是还是不理想高并发的情况下偶尔会丢数据或者job直接卡死的情况,所以最后使用官方的jdbc来连接找了一波在站内看到大佬的帖子。里面提到的开源项目都做过尝试,最后在博客园翻到一个博主提供了jdbc的示例,于是在他的基础上改了一波。

#官方

JDBC | Apache Flink

#csdn

flink-connector-clickhouse_flink clickhouse connector-CSDN博客

#博客园

https://www.cnblogs.com/sqhhh/p/15897275.html

最后基于官方jdbc的驱动重新封装直接丢上去跑了一波感觉还行,就此分享记录下。

flink环境为

 <scala.version>2.11</scala.version>
 <flink.version>1.14.4</flink.version>

相关jdbc驱动

 <!-- ClickHouse JDBC 驱动依赖 -->
        <dependency>
            <groupId>ru.yandex.clickhouse</groupId>
            <artifactId>clickhouse-jdbc</artifactId>
            <version>0.3.1</version>
        </dependency>

        <!-- mysql JDBC 驱动依赖 -->
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <version>8.0.29</version>
        </dependency>
    public SinkSingleDB(String sql, JdbcStatementBuilder<T> jdbcStatementBuilder,
                        Properties props) {
        sink = JdbcSink.sink(
                sql,
                jdbcStatementBuilder,
                new JdbcConnectionOptions.JdbcConnectionOptionsBuilder()
                        .withUrl("jdbc:" + props.getProperty(Constants.DRIVE) + "://" + props.getProperty(Constants.HOST) + "/" + props.getProperty(Constants.DATABASE))
                        .withDriverName(SinkSourceEnums.getDriverByType(props.getProperty(Constants.DRIVE)))
                        .withUsername(props.getProperty(Constants.USERNAME))
                        .withPassword(props.getProperty(Constants.PASSWORD))
                        .build()
        );
    }
public SinkSingleDB(String sql, JdbcStatementBuilder<T> jdbcStatementBuilder,
                        Properties props, Boolean options) {
        sink = JdbcSink.sink(
                sql,
                jdbcStatementBuilder,
                JdbcExecutionOptions.builder()
                        .withBatchIntervalMs(Long.valueOf(props.getProperty(Constants.BATCH_INTERVAL_MS, DEFAULT_INTERVAL_MILLIS)))
                        .withBatchSize(Integer.valueOf(props.getProperty(Constants.BATCH_SIZE, DEFAULT_SIZE)))
                        .withMaxRetries(Integer.valueOf(props.getProperty(Constants.MAX_RETRIES, DEFAULT_MAX_RETRY_TIMES)))
                        .build(),
                new JdbcConnectionOptions.JdbcConnectionOptionsBuilder()
                        .withUrl("jdbc:" + props.getProperty(Constants.DRIVE) + "://" + props.getProperty(Constants.HOST) + "/" + props.getProperty(Constants.DATABASE))
                        .withDriverName(SinkSourceEnums.getDriverByType(props.getProperty(Constants.DRIVE)))
                        .withUsername(props.getProperty(Constants.USERNAME))
                        .withPassword(props.getProperty(Constants.PASSWORD))
                        .build()
        );
    }

当前值连接jdbc的老手应该很熟悉,唯一区别就是第二指定了批处理可以按照自己的性能要求直接提交次数和数量。

如果不指定就是默认时间。时间间隔和数据量满足一个则提交,需要注意的是时间间隔为0是不限,可以查看官方文档

其他的基本操作都是一样的,都是通过PreparedStatement来指定构造sql的参数,一开始找到的是直接封装bean对象,但是实际场景下map的操作有点多比较方便所以添加了一个map的构造参数方法

使用的时候在最后addsink之前添加数据的相关配置连接信息

最后调用方法就可以了

最后源码都丢上,有需要的可以点击查看,里面有测试类可以自己添加其他数据源。

Flink-JDBC-Connector: 当前项目是基于jdbc来写入flink数据到数据库的

### 回答1: Apache Flink 是一个分布式计算框架,可以用于实时流处理和批处理。Flink 提供了许多内置的 Sink,其中包括将数据写入 MySQL 数据库的 Sink。下面是使用 Flink 将数据写入 MySQL 的示例代码: ```java DataStream<Tuple2<String, Integer>> dataStream = ...; // 从某个地方获取数据流 // 将数据写入 MySQL dataStream.addSink(new JdbcSink<>(getConnection(), // 获取数据库连接 "INSERT INTO my_table (name, count) VALUES (?, ?)", // 插入语句 new JdbcStatementBuilder<Tuple2<String, Integer>>() { // 用于构建 PreparedStatement 的类 @Override public void accept(PreparedStatement preparedStatement, Tuple2<String, Integer> t) throws SQLException { // 设置参数 preparedStatement.setString(1, t.f0); preparedStatement.setInt(2, t.f1); } })); ``` 在上面的代码中,我们使用了 Flink 提供的 JdbcSink,将数据流中的 Tuple2<String, Integer> 类型的数据写入 MySQL 数据库。我们需要提供数据库连接、插入语句和用于构建 PreparedStatement 的类。在 accept 方法中,我们设置了 PreparedStatement 的参数,将数据写入数据库。 需要注意的是,我们需要在项目中添加 MySQL JDBC 驱动程序的依赖,以便在代码中使用。 ### 回答2: flink是一个用于数据流处理和批处理的开源框架,而MySQL是一个流行的关系型数据库管理系统。在flink中,可以使用sink来将数据流或批处理结果输出到MySQL中。 要实现flink sinkMySQL,首先需要创建一个StreamingExecutionEnvironment或ExecutionEnvironment对象,然后根据需要定义数据源和转换操作。接下来,通过定义一个JDBCOutputFormat,将转换后的数据流或批处理结果写入MySQL数据库。JDBCOutputFormat是flink提供的用于将数据写入关系型数据库的输出格式。 在JDBCOutputFormat的构造函数中,需要提供MySQL数据库的连接信息,例如URL、用户名和密码。然后,可以使用writeRecord方法将转换后的数据写入MySQL数据库。在写入数据之前,还可以使用setBatchInterval方法设置批量提交的间隔时间,以减少数据库的压力。 除了使用JDBCOutputFormat,还可以使用flink提供的Table API或SQL API来将数据写入MySQL。通过将MySQL作为一个外部系统注册到flink中,并定义一个INSERT INTO语句,可以直接将数据流或批处理结果插入到MySQL表中。 总之,flink可以通过使用JDBCOutputFormat、Table API或SQL API来将数据流或批处理结果输出到MySQL数据库中。这样可以方便地将flink处理的数据持久化到关系型数据库中,以供后续的分析和应用程序使用。 ### 回答3: Flink是一种开源的流式处理引擎,可以用来实现实时数据流处理。而MySQL是一个关系型数据库管理系统,它可以用来存储和管理结构化数据。 在Flink中,可以使用JDBC Sink将数据流输出到MySQL数据库中。首先,我们需要在Flink的配置文件中添加相应的依赖,以便能够与MySQL进行连接。 接下来,我们需要创建一个自定义的Sink函数,用来将数据流写入MySQL数据库。这个Sink函数需要继承自RichSinkFunction类,并实现其invoke方法。在invoke方法中,我们可以通过JDBC连接将数据写入MySQL数据库。 在Sink函数中,我们需要在open方法中获取MySQL数据库的连接,并在invoke方法中执行插入操作。同时,我们还可以在Sink函数中实现其他的数据处理逻辑,比如数据转换、筛选等。 最后,我们将Sink函数与Flink的DataStream进行关联,即可将数据流输出到MySQL数据库中。在使用Flink的execute方法执行任务时,数据流会经过Sink函数,并将结果写入MySQL数据库。 总结来说,Flink可以通过JDBC Sink将数据流输出到MySQL数据库中,我们只需要编写相应的Sink函数,并将其与DataStream关联起来即可实现。 需要注意的是,在使用Flink Sink写入MySQL数据库时,要确保数据库连接的可靠性和性能。可以考虑使用连接池来管理数据库连接,以提高系统的稳定性和吞吐量。同时,还要注意处理可能出现的异常情况,比如数据写入失败等。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值