一、时间语义
Event Time:事件创建的时间
Ingestion Time:数据进入Flink的时间
Processing Time:执行算子操作的本地系统时间,与机器相关
设置时间语义
StreamExecutionEnvironment environment = StreamExecutionEnvironment.getExecutionEnvironment();
environment.setStreamTimeCharacteristic(TimeCharacteristic.EventTime);
当Flink以Event Time模式处理数据流时,它会根据数据里的时间戳来处理基于时间的算子
考虑到网络或者分布式等原因,现实数据流的数据可能是乱序的
举个例子:
数据流有如下数据:1,2,3,4,5,6 当5到了触发window算子操作
理想情况是5到了,那么比我小的都到了,触发window操作没问题
但是实际情况,数据有可能乱序,5到了,不一定比5小的都到,如下图所示3,2都没到
如何解决乱序数据带来的问题?
flink引入了watermark
二、waterMark(水位线)
对于乱序数据流而言,遇到一个时间戳达到窗口关闭时间,不应该立刻触发窗口计算,而是等待一段时间,等迟到的数据来了再关闭窗口。
watermark是一种衡量Event Time进展的机制,可以设定延迟触发
数据流中的watermark用于表示事件的时间小于watermark的数据都已经到达,因此window的执行也是由watermark触发
watermark=进入flink的最大事件时间-指定的延迟时间
1、watermark特点
(1)watermark是一条特殊的数据记录
(2)watermark必须单调递增,以确保任务的事件时间时钟在向前推进
(3)watermark与数据的时间戳相关
(4)在多并行度下,watermark会有一个对齐机制,选取所有并行watermark中最小的。
2、程序中使用watermark
Flink暴露TimestampAssigner接口供自定义实现抽取时间戳和生成watermark
BoundedOutOfOrdernessTimestampExtractor是处理乱序数据
dataStream.assignTimestampsAndWatermarks(new BoundedOutOfOrdernessTimestampExtractor<String>(Time.seconds(1)) {
@Override
public long extractTimestamp(String element) {
JSONObject jsonObject=JSONObject.parseObject(element);
Long timestamp = jsonObject.getLong("timestamp");//获取事件时间戳
return timestamp;
}
});
(1)AssignerWithPeriodicWatermarks
1)周期性的生成watermark,系统会周期性的将watermark插入到流中
2)默认周期200毫秒,可以使用ExecutionConfig方法设置
environment.getConfig().setAutoWatermarkInterval(1000);
3)升序和前面乱序的处理BoundedOutOfOrdernessTimestampExtractor都是基于周期性watermark
举例:
dataStream.assignTimestampsAndWatermarks(new AssignerWithPeriodicWatermarks<String>(){
long bound=60*1000;//延迟1分钟
long maxTimestamp=0;
@Override
public long extractTimestamp(String element, long previousElementTimestamp) {
JSONObject jsonObject=JSONObject.parseObject(element);
Long timestamp = jsonObject.getLong("timestamp");//获取事件时间戳
if(maxTimestamp==0){
maxTimestamp=timestamp;
}else{
maxTimestamp=Math.max(maxTimestamp,timestamp);
}
return timestamp;
}
@Nullable
@Override
public Watermark getCurrentWatermark() {
return new Watermark(maxTimestamp-bound);
}
});
(2)AssignerWithPunctuatedWatermarks
没有时间周期规律,可打断生成watermark
举例:
dataStream.assignTimestampsAndWatermarks(new AssignerWithPunctuatedWatermarks<String>(){
long bound=60*1000;//延迟1分钟
@Override
public long extractTimestamp(String element, long previousElementTimestamp) {
JSONObject jsonObject=JSONObject.parseObject(element);
Long timestamp = jsonObject.getLong("timestamp");//获取事件时间戳
return timestamp;
}
@Nullable
@Override
public Watermark checkAndGetNextWatermark(String lastElement, long extractedTimestamp) {
JSONObject jsonObject=JSONObject.parseObject(lastElement);
String name = jsonObject.getString("name");
if(name.equals("zs")) {
return new Watermark(extractedTimestamp-bound);
}
return null;
}
});