时间、窗口、水印、迟到数据这四个知识点几乎是Flink这个框架最难点。我之前发了很多文章来解释。很多同学仍然理解不了。
事实上这跟Flink的文档不全有直接关系。在这个问题上官网的资料不够,学习成本巨大。
希望这篇文章能解答读者在这个问题上的困惑。本文结合源码和实例讲解。
Flink支持根据事件时间处理,数据流中的每条数据都需要具有各自的时间戳,代表着数据的产生时间【事件时间】。
在分布式系统中,数据流的采集通常都是有延迟的,可能是网络原因啊,程序原因啊什么的。所以当数据到达Flink程序中的时候,问题就来了,这些数据都要进行处理吗?有可能其中一部分数据已经延迟了好几个小时了,这对于实时性较强的业务场景是不能容忍的!
这时候水印就应运而生了,水印的目的就是为了解决乱序的数据问题,可以在时间窗口内根据事件时间来进行业务处理,对于乱序的有延迟的数据可以在一定时间范围内进行等待,那这个时间范围是怎么计算的呢?
我们先来捋捋思路
数据在源源不断的进入flink,我们设置好window的大小为5s,flink会以5s来将每分钟划分为连续的多个窗口。
则flink划分的时间窗口为(左闭右开):
进入flink的第一条数据会落在一个时间窗口内,假设数据的事件时间为13s(小时和分不重要,因为窗口大小的度量单位是秒),则落入的窗口是【10-15】。对于存在延迟的数据,我们能容忍的时间是3s,超过3s我就不等你了,继续进行窗口操作。
这里就要提到一个知识点:Window的触发条件是什么,什么时候开始进行window操作?
- 该窗口中存在数据
- 事件时间到达窗口的结束时间
好,知道了window触发条件后我们继续分析,第一个条件肯定满足的,只要有数据就行了。
第二个条件,窗口的结束时间是15s,但是我们加了水印,允许数据延迟3秒,换句话说就是本来在15秒这个窗口就应该开始统计数据了,但是为了等一些延迟的数据,我要在18s才开始进行统计
【10-15】窗口触发的条件就是:存在一条数据的事件时间大于等于18s
下面我们用实例来验证:
大概讲解一下代码的流程:
1、监听某主机的9000端口,读取socket数据(格式为 name:timestamp)
2、给当前进入flink程序的数据加上waterMark,值为eventTime-3s
3、根据name值进行分组,根据窗口大小为5s划分窗口,依次统计窗口中各name值的数据
4、启动Job