【时间】2022.06.07 周二
【题目】【Flink入门(5)】Flink的时间语义与Watermark
本专栏是尚硅谷Flink课程的笔记与思维导图。
目录
引言
- flink中有3种时间语义,这里主要讲EvenTime事件时间,从数据的时间戳中提取,属于事件创建(数据产生)的时间,区别于数据到达时间(Ingestion Time)和处理时间(Processing Time)。
- Watermark(水位线)是一种处理乱序数据的机制,相当于扩宽window窗口以处理迟到数据。
一、时间(Time)语义
三种时间语义
二、Watermark(水位线)
2.1 概述
乱序数据的影响
2.2 特点
WaterMark的作用是延迟关闭前一个窗口的时间,以处理迟到的数据:
2.3 Watermark相关知识
1)向下游传递
上游Task的watermark广播给下游Task,下游Task取最小WM:
2)在stream中引入(代码)
例子:
public class WindowTest3_EventTimeWindow {
public static void main(String[] args) throws Exception {
StreamExecutionEnvironment env = StreamExecutionEnvironment.getExecutionEnvironment();
// Flink1.12.X 已经默认就是使用EventTime了,所以不需要这行代码
// env.setStreamTimeCharacteristic(TimeCharacteristic.EventTime);
env.getConfig().setAutoWatermarkInterval(100);
// socket文本流
DataStream<String> inputStream = env.socketTextStream("localhost", 7777);
// 转换成SensorReading类型,分配时间戳和watermark
DataStream<SensorReading> dataStream = inputStream.map(line -> {
String[] fields = line.split(",");
return new SensorReading(fields[0], new Long(fields[1]), new Double(fields[2]));
})
//
// 旧版 (新版官方推荐用assignTimestampsAndWatermarks(WatermarkStrategy) )
// 升序数据(不乱序)设置事件时间和watermark
//.assignTimestampsAndWatermarks(new AscendingTimestampExtractor<SensorReading>() {
// @Override
// public long extractAscendingTimestamp(SensorReading element) {
// return element.getTimestamp() * 1000L;
// }
//})
// 旧版 (新版官方推荐用assignTimestampsAndWatermarks(WatermarkStrategy) )
// 乱序数据设置时间戳和watermark
.assignTimestampsAndWatermarks(new BoundedOutOfOrdernessTimestampExtractor<SensorReading>(Time.seconds(2)) {//需要传入参数:乱序程度
@Override
public long extractTimestamp(SensorReading element) {
return element.getTimestamp() * 1000L; //毫秒
}
});
OutputTag<SensorReading> outputTag = new OutputTag<SensorReading>("late") {
};
// 基于事件时间的开窗聚合,统计15秒内温度的最小值
SingleOutputStreamOperator<SensorReading> minTempStream = dataStream.keyBy("id")
.timeWindow(Time.seconds(15))
.allowedLateness(Time.minutes(1))
.sideOutputLateData(outputTag)
.minBy("temperature");
minTempStream.print("minTemp");
minTempStream.getSideOutput(outputTag).print("late");
env.execute();
}
}
3)设置合适的WaterMark延时时间
4)窗口起始点计算
其中offset是时区偏移量。
2.4 Flink处理迟到数据的3层保障
例子:
public class WindowTest3_EventTimeWindow {
public static void main(String[] args) throws Exception {
StreamExecutionEnvironment env = StreamExecutionEnvironment.getExecutionEnvironment();
env.setParallelism(1);
env.setStreamTimeCharacteristic(TimeCharacteristic.EventTime);
env.getConfig().setAutoWatermarkInterval(100);
// socket文本流
DataStream<String> inputStream = env.socketTextStream("localhost", 7777);
// 转换成SensorReading类型,分配时间戳和watermark
DataStream<SensorReading> dataStream = inputStream.map(line -> {
String[] fields = line.split(",");
return new SensorReading(fields[0], new Long(fields[1]), new Double(fields[2]));
})
// 乱序数据设置时间戳和watermark
.assignTimestampsAndWatermarks(new BoundedOutOfOrdernessTimestampExtractor<SensorReading>(Time.seconds(2)) {
@Override
public long extractTimestamp(SensorReading element) {
return element.getTimestamp() * 1000L;
}
});
OutputTag<SensorReading> outputTag = new OutputTag<SensorReading>("late") {
};
// 基于事件时间的开窗聚合,统计15秒内温度的最小值
SingleOutputStreamOperator<SensorReading> minTempStream = dataStream.keyBy("id")
.timeWindow(Time.seconds(15)) //时间窗口大小15s
.allowedLateness(Time.minutes(1))//允许延时1m,这是基于处理时间的(即窗口执行时间),窗口操作后,在1min内,每来一个迟到数据,就输出一个结果。
.sideOutputLateData(outputTag)//测输出流
.minBy("temperature");
minTempStream.print("minTemp");
minTempStream.getSideOutput(outputTag).print("late");
env.execute();
}
}