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。不同的时,它可以修复上面情况的延迟,即允许数据在窗口到期后一定时间内在接受当前窗口的数据。

posted @ 2020-03-04 17:08  ongbo  阅读(58)  评论(0)    收藏  举报