Flink水涨船高:EventTime和WaterMark
之前对于ProcessingTime,作为一种当前计算机的处理时间,我们不用在意它数据到来的顺序,一切以我当前计算机的时间为准,不用协调其他的计算机节点。
但是呢对于EventTime,拿我们Web网站的日志来说,EventTime即是日志中的时间戳,但是发送数据的情况不可能总是那么理想,到达Flink的顺序不可能刚好是时间戳的顺序,为了控制这种乱序的情况,引入了WaterMark,中文翻译暂时是水位线,也可以翻译成水印,但是个人忠于水位线
它作为一种衡量EventTime时间的标准,也作为事件传输在流中
串行中的WaterMark

**上面这个图中,方框中的数字代表EventTime,而WaterMark插入在这些时间之中,它代表所有<=T的时间戳都来了。比如W(11)就说明<=11的时间的事件都来了。但是这样也难免会出现一些问题,比如硬是有一些之前的数据延迟到达,
并行中的WaterMark

对于AB:Map算子和CD的window算子,而AB是同一算子并行计算,CD是同一算子并行计算。
在A点的watermark是29,在B的watermark是17,那么通过到下个算子后,因为中间有个过程类似于分流或者说shuffle,导致A和B的watermark都进入了C和D
对于C和D来说,他们都接受到多个WaterMark,这时候他们会选择最小的那个作为自己的WaterMark,然后将自己的WaterMark发给下游,也就四下一个算子。
自定义发出WaterMark
通过实现AssignerWithPeriodicWatermarks或者AssignerWithPunctuatedWatermarks接口来自己发出时间戳。前者是定期发出,后者是基于某些特殊的元素发出。
Flink中提供的WaterMark实现
Assigners with ascending timestamps
递增的时间戳实现:
DataStream<MyEvent> stream = ...
DataStream<MyEvent> withTimestampsAndWatermarks =
stream.assignTimestampsAndWatermarks(new AscendingTimestampExtractor<MyEvent>() {
@Override
public long extractAscendingTimestamp(MyEvent element) {
return element.getCreationTime();
}
});

看他是实现了AssignerWithPeriodicWatermarks,它是一种理想状况,即所有的元素都按序到达了,
Assigners allowing a fixed amount of lateness
某些情况下,比如当前节点WaterMark为19,所以认为<19的事件都认为到了,但是就是有可能有个17的延迟了,所以这时候就需要我们允许这种延迟的情况
DataStream<MyEvent> stream = ...
DataStream<MyEvent> withTimestampsAndWatermarks =
stream.assignTimestampsAndWatermarks(new BoundedOutOfOrdernessTimestampExtractor<MyEvent>(Time.seconds(10)) {
@Override
public long extractTimestamp(MyEvent element) {
return element.getCreationTime();
}
});

它是基于AssignerWithPeriodicWatermarks接口实现,和上面一样,都是周期性的发出WaterMark。不同的时,它可以修复上面情况的延迟,即允许数据在窗口到期后一定时间内在接受当前窗口的数据。

浙公网安备 33010602011771号