1.添加运行环境和设置时间语义
如果是迟到数据处理就只能在事件时间语义下使用,如果是一般数据使用侧输出流就看业务需求是按什么条件进行分流eg:如果按照数据中的温度进行划分高温流和低温流,可以直接使用处理时间语义(默认值,不需要设置)。如果业务需要数据中的下单时间进行相关统计,就需要开启事件时间
StreamExecutionEnvironment env = StreamExecutionEnvironment.getExecutionEnvironment();
//设置全局并行度
env.setParallelism(1);
//开启事件时间
env.setStreamTimeCharacteristic(TimeCharacteristic.EventTime);
2.事件时间语义下需要设置watermark
为流设置watermark,如果是乱序数据就需要使用BoundOutOfOrdernessTimestampExtractor,如果时间是严格递增,则使用AscendingTimestampExtractor
BoundOutOfOrdernessTimestampExtractor需要设置延迟时间,一般取逆序时间的最大值eg:01:00 02:01 01:50 01:20…当前最大逆序为2:01和1:20即41s
//为流设置watermark,如果是乱序数据就需要使用BoundOutOfOrdernessTimestampExtractor,如果时间是严格递增的就可以使用
//AscendingTimestampExtractor
DataStreamSource<String> inputStream = env.readTextFile("hello.csv");
DataStream<UserBehavior> mapStream = inputStream.map(line -> {
String[] split = line.split(",");
return new Person(Long.valueOf(split[0]), Long.valueOf(split[1]), Integer.valueOf(split[2]),
split[3], Long.valueOf(split[4]));
})
.assignTimestampsAndWatermarks(new BoundedOutOfOrdernessTimestampExtractor
<Person>(Time.seconds(2L)) {//设置延迟时间为2s
@Override
public long extractTimestamp(Person element) {
return element.getTimestamp()*1000;//每个数据的实际事件时间,这里乘1000是因为原始数据使
//用的时间戳是s,需要转换为毫秒
}
})
3.设置Output标签
OutputTag<Person> outputtag=new Output<>("hello"){};
4.开启侧输出流
- 迟到数据可以使用特殊的侧输出流形式
//1).开启窗口
DataStream<Person> mainStream=mapStream.keyBy("id).timeWindow(Time.seconds(15))
//2).设置允许的延迟数据时间
.allowedLateness(Time.minutes(1))
//添加侧输出流标签
.sideOutputLateData(outputtag);
大招:所有想要使用侧输出流的情况都可以使用底层函数process
DataStream<String> mainStream=mapStream.keyBy("id).timeWindow(Time.seconds(15))
.process(new MyProcessFunction());
//通过process获取到的流数据的上下文设置侧输出流
public static class MyProcessFunction extends KeyedProcessFunction<String,Person,String>{
@Override
public void processElement(Person value, Context ctx, Collector<String> out) throws Exception {
if(value.getTimestamp<10000000){//假设我们将时间戳小于10000000作为分界,分到两个流中
ctx.output(outputtag,value);
}else{
out.collect(value);
}
}
}
5.使用侧输出流
//简单应用-打印:
//获取侧输出流
DataStream<Person> sideOutput = mainStream.getSideOutput(outputtag);
//打印
sideOutput.print("sideoutputstream");
//主流打印
mainStream。print("mainstream");
//执行任务
env.execute();