Flink-JdbcSink

package com.atguigu.flink.datastream.sink;

import com.atguigu.flink.func.ClickSource;
import com.atguigu.flink.pojo.Event;
import org.apache.flink.connector.jdbc.JdbcConnectionOptions;
import org.apache.flink.connector.jdbc.JdbcExecutionOptions;
import org.apache.flink.connector.jdbc.JdbcSink;
import org.apache.flink.connector.jdbc.JdbcStatementBuilder;
import org.apache.flink.streaming.api.datastream.DataStreamSource;
import org.apache.flink.streaming.api.environment.StreamExecutionEnvironment;
import org.apache.flink.streaming.api.functions.sink.SinkFunction;

import java.sql.PreparedStatement;
import java.sql.SQLException;

/**
 * @author WEIYUNHUI
 * @date 2023/6/14 14:10
 *
 * JdbcSink:
 *   1. 常规写入 sink()
 *   2. exactlyOnceSink() 支持分布式写入 , 支持分布式事务 ,  支持EOS
 *
 * JDBC步骤:
 *   注册驱动
 *   获取连接
 *   编写SQL
 *   预编译SQL
 *   设置参数
 *   执行SQL
 *   处理结果
 *   关闭连接
 *
 *
 *   写入方式:
 *      1. 直接写入   insert into clicks (xxx) values (xxx)
 *      2. 幂等写入(有主键)
 *            replace into clicks(xxx) values (xxx)
 *            insert into clicks(user ,url ,ts ) values (?,?,?) on Duplicate key update
 */
public class Flink04_JdbcSink {
    public static void main(String[] args) {
        StreamExecutionEnvironment env = StreamExecutionEnvironment.getExecutionEnvironment();
        env.setParallelism(1);
        DataStreamSource<Event> ds = env.addSource(new ClickSource());
        ds.print("input");

        //将流中的数据写入到Mysql
        SinkFunction<Event> jdbcSink = JdbcSink.<Event>sink(
                //"insert into clicks1 (user ,url ,ts ) values(?,?,?)",
                "replace into clicks1(user, url, ts ) values(?,?,?)" ,
                new JdbcStatementBuilder<Event>() {
                    @Override
                    public void accept(PreparedStatement preparedStatement, Event event) throws SQLException {
                        preparedStatement.setString(1, event.getUser());
                        preparedStatement.setString(2, event.getUrl());
                        preparedStatement.setLong(3, event.getTs());
                    }
                },

                JdbcExecutionOptions.builder()
                        .withBatchSize(5)  // 批写大小
                        .withBatchIntervalMs(10000)  // 批次间隔时间, 超过指定时间也要写入
                        .withMaxRetries(3)  //重试次数
                        .build(),

                new JdbcConnectionOptions.JdbcConnectionOptionsBuilder()
                        .withDriverName("com.mysql.cj.jdbc.Driver")
                        .withUrl("jdbc:mysql://hadoop102:3306/test")
                        .withUsername("root")
                        .withPassword("000000")
                        .build()
        );

        //旧的API
        ds.addSink(jdbcSink) ;

        try {
            env.execute();
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }
}


package com.atguigu.flink.datastream.sink;

import com.atguigu.flink.func.ClickSource;
import com.atguigu.flink.pojo.Event;
import com.mysql.cj.jdbc.MysqlXADataSource;
import org.apache.flink.connector.jdbc.*;
import org.apache.flink.streaming.api.datastream.DataStreamSource;
import org.apache.flink.streaming.api.environment.StreamExecutionEnvironment;
import org.apache.flink.streaming.api.functions.sink.SinkFunction;
import org.apache.flink.util.function.SerializableSupplier;

import javax.sql.XADataSource;
import java.sql.PreparedStatement;
import java.sql.SQLException;

/**
 * @author WEIYUNHUI
 * @date 2023/6/14 14:10
 *
 * JdbcSink:
 *   1. 常规写入 sink()
 *   2. exactlyOnceSink() 支持分布式写入 , 支持分布式事务 ,  支持EOS
 *
 * XASink(了解):
 *    注意事项:
 *       1. 先明确当前使用的数据是否支持XA
 *       2. 如果使用的是Mysql或者PostgreSQL ,在一个连接上只支持一个XA事务。
 *          JdbcExactlyOnceOptions.builder()
 *          .withTransactionPerConnection(true)
 *          .build();
 *       3. 如果使用MySQL XA , 需要提前给mysql的用户授权 XA_RECOVER_ADMIN
 *       4. 要求重试次数只能是 0。 JdbcExecutionOptions.maxRetries == 0
 *
 *       5. 开启Flink的检查点。
 */
public class Flink05_JdbcXASink {
    public static void main(String[] args) {
        StreamExecutionEnvironment env = StreamExecutionEnvironment.getExecutionEnvironment();
        env.setParallelism(1);
        env.enableCheckpointing(5000L);
        DataStreamSource<Event> ds = env.addSource(new ClickSource());
        ds.print("input");

        //将流中的数据写入到Mysql
        SinkFunction<Event> jdbcSink = JdbcSink.<Event>exactlyOnceSink(
                //"insert into clicks1 (user ,url ,ts ) values(?,?,?)",
                "replace into clicks1(user, url, ts ) values(?,?,?)",
                new JdbcStatementBuilder<Event>() {
                    @Override
                    public void accept(PreparedStatement preparedStatement, Event event) throws SQLException {
                        preparedStatement.setString(1, event.getUser());
                        preparedStatement.setString(2, event.getUrl());
                        preparedStatement.setLong(3, event.getTs());
                    }
                },

                JdbcExecutionOptions.builder()
                        .withBatchSize(5)  // 批写大小
                        .withBatchIntervalMs(10000)  // 批次间隔时间, 超过指定时间也要写入
                        .withMaxRetries(0)  //重试次数
                        .build(),

                JdbcExactlyOnceOptions.builder()
                        .withTransactionPerConnection(true)
                        .build(),

                new SerializableSupplier<XADataSource>() {
                    @Override
                    public XADataSource get() {
                        //按照使用的数据库来创建对应的XADataSource
                        MysqlXADataSource mysqlXADataSource = new MysqlXADataSource();
                        mysqlXADataSource.setUrl("jdbc:mysql://hadoop102:3306/test");
                        mysqlXADataSource.setUser("root");
                        mysqlXADataSource.setPassword("000000");
                        return mysqlXADataSource;
                    }
                }
        );

        //旧的API
        ds.addSink(jdbcSink) ;

        try {
            env.execute();
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
在 Flink 中,`JdbcSink` 是将数据写入 JDBC 数据库的 Sink,如果数据无法写入数据库,则会抛出异常。可以通过以下方式进行捕获: 1. 在 `JdbcSink` 中重写 `invoke` 方法,并在方法中捕获异常。例如: ```java public class MyJdbcSink extends JdbcSink<Tuple2<String, Integer>> { @Override public void invoke(Connection connection, Tuple2<String, Integer> value, Context context) throws Exception { try { // 处理数据 } catch (Exception e) { // 捕获异常 } super.invoke(connection, value, context); } } ``` 2. 在 `StreamExecutionEnvironment` 中设置全局异常处理器。例如: ```java StreamExecutionEnvironment env = StreamExecutionEnvironment.getExecutionEnvironment(); env.getConfig().setGlobalJobParameters(params); env.setStreamTimeCharacteristic(TimeCharacteristic.ProcessingTime); env.setParallelism(1); env.setStreamTimeCharacteristic(TimeCharacteristic.ProcessingTime); env.getConfig().setGlobalJobParameters(params); env.setParallelism(1); env.getCheckpointConfig().setCheckpointingMode(CheckpointingMode.EXACTLY_ONCE); env.getCheckpointConfig().setCheckpointTimeout(60000); env.setStreamTimeCharacteristic(TimeCharacteristic.ProcessingTime); env.getConfig().setGlobalJobParameters(params); env.setParallelism(1); // 设置全局异常处理器 env.getConfig().setGlobalJobParameters(params); env.getConfig().setRestartStrategy(RestartStrategies.fixedDelayRestart( 3, // 尝试重启的次数 Time.of(10, TimeUnit.SECONDS) // 时间间隔 )); env.getConfig().setGlobalJobParameters(params); env.setParallelism(1); // 添加 JdbcSink DataStream<Tuple2<String, Integer>> dataStream = ...; dataStream.addSink(new MyJdbcSink()); env.execute("My Flink Job"); ``` 通过以上两种方式,可以捕获 `JdbcSink` 写入数据时产生的异常。需要注意的是,捕获异常后需要根据实际情况进行处理,例如重试或将异常数据写入死信队列等。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值