1、写入文件
(1)读取数据:
DataStream<String> linesDS = env.socketTextStream("master", 8888);
(2)定义一个file sink:
//定义file sink
FileSink<String> sink = FileSink
//指定数据的格式
.<String>forRowFormat(new Path("flink/data/words"), new SimpleStringEncoder<>("UTF-8"))
//指定滚动策略
.withRollingPolicy(
DefaultRollingPolicy.builder()
//包含了至少10秒的数据量
.withRolloverInterval(Duration.ofSeconds(10))
//从没接收延时10秒之外的新纪录(间隔了10s未出现新的记录生成新的文件)
.withInactivityInterval(Duration.ofSeconds(10))
//文件大小已经达到 1MB(写入最后一条记录之后)
.withMaxPartSize(MemorySize.ofMebiBytes(1))
.build())
.build();
注意:泛型与读取数据泛型保持一致
滚动策略只在流处理下编写,批处理无滚动策略
(3)使用file sink
//使用file sink
linesDS.sinkTo(sink);
2、打印文件
即print
3、自定义sink
方法与自定义source类似
(1)定义一个sink类:
class MySink implements SinkFunction<String>{
@Override
public void invoke(String value, Context context) throws Exception{
//自定义数据sink位置
System.out.println("自定义sink:"+value);
}
}
(2)在主类中调用addSink()使用
public class Demo02MySink {
public static void main(String[] args)throws Exception {
StreamExecutionEnvironment env = StreamExecutionEnvironment.getExecutionEnvironment();
DataStream<String> linesDS = env.socketTextStream("master", 8888);
//使用自定义sink
linesDS.addSink(new MySink());
env.execute();
}
}
4、自定义MySQL sink 统计单词数量
主类:
public class Demo03MySQLSink {
public static void main(String[] args)throws Exception{
StreamExecutionEnvironment env = StreamExecutionEnvironment.getExecutionEnvironment();
DataStreamSource<String> wordsDS = env.socketTextStream("master", 8888);
//统计单词数量
SingleOutputStreamOperator<Tuple2<String, Integer>> tupleDS = wordsDS
.map(w -> Tuple2.of(w, 1), Types.TUPLE(Types.STRING, Types.INT));
SingleOutputStreamOperator<Tuple2<String, Integer>> wordcountDS = tupleDS
.keyBy(k -> k.f0)
.sum(1);
//将统计结果保存到数据
wordcountDS.addSink(new mySQLSink());
env.execute();
}
}
自定义mySQLSink类:
class mySQLSink implements SinkFunction<Tuple2<String, Integer>>{
/**
* invoke方法每一条数据执行一次
*/
@Override
public void invoke(Tuple2<String, Integer> value, Context context) throws Exception{
//1、加载驱动
Class.forName("com.mysql.jdbc.Driver");
//2、创建数据库连接
Connection con = DriverManager.getConnection("jdbc:mysql://master:3306/bigdata29", "root", "123456");
//3、编写sql语句
PreparedStatement stat = con.prepareStatement("insert into word_count values(?,?)");
stat.setString(1,value.f0);
stat.setInt(2,value.f1);
//执行sql
stat.execute();
//关闭数据连接
stat.close();
con.close();
}
}
mysql连接的优化:
继承RichSinkFunction类重写open与close方法,优化资源浪费问题。
/**
* 自定义sink将数据保存到mysql
* RichSinkFunction:多了open和close方法,用于打开和关闭连接
* SinkFunction
*/
class mySQLSink extends RichSinkFunction<Tuple2<String, Integer>> {
Connection con;
PreparedStatement stat;
/**
* open方法会在任务启动的时候,每一个task中执行一次
*/
@Override
public void open(Configuration parameters) throws Exception {
//1、加载驱动
Class.forName("com.mysql.jdbc.Driver");
//2、创建数据库连接
con = DriverManager.getConnection("jdbc:mysql://master:3306/bigdata29?useSSL=false", "root", "123456");
//3、编写sql语句
stat = con.prepareStatement("replace into word_count values(?,?)");
}
/**
* invoke方法每一条数据执行一次
*/
@Override
public void invoke(Tuple2<String, Integer> value, Context context) throws Exception{
stat.setString(1,value.f0);
stat.setInt(2,value.f1);
//执行sql
stat.execute();
}
/**
* close方法会在任务结束的时候,每一个task中执行一次
*/
@Override
public void close() throws Exception {
//关闭数据连接
stat.close();
con.close();
}
}