在数据实时分析的时候,关注的是数据的顺序性,特别是用Flink接收数据的时候考虑到流量在突然到来的峰值,flink反压导致了数据到达处理task的时候时间怎么对齐的问题。这里就需要用到flink 水位线了。
通俗来理解 Flink有两个时间: EventTime 和 ProcessTime
(1)EventTime 是从原始消息中提取出来的
(2)ProcessTime 是 Flink 自己提供的。
假设一个场景,我们需要统计一个URL,在5分钟内被访问的次数,数据结构如下:
URL | STRING |
ACCESSTIME | LONG |
SYSTEMTIME | LONG |
ACCESSTIME是这条记录在用户访问网站时产生的时间戳,我们可以认为ACCESSTIME对应到Flink,就是EventTime,后续的统计也是以这个时间为基准来做统计时间窗口的基准字段。
SYSTEMTIME是数据到达FLINK时的时间戳。
如下,数据记录,由于数据被延迟,实际到达flink的时间均存在了分钟级的延迟,因此systemtime的都是晚于accesstime几分钟的,按照systemtime进行窗口的统计,得到的数据和accesstime得到的数据是完全不一样的:
①http://www.ssss.com/aaa,20220305120122,20220305120900
②http://www.ssss.com/aaa,20220305120232,20220305120901
③http://www.ssss.com/bbb,20220305120648,20220305120902
④http://www.ssss.com/aaa,20220305120441,20220305121202
⑤http://www.ssss.com/ccc,20220305120710,20220305121204
⑥http://www.ssss.com/bbb,20220305120927,20220305121204
⑦http://www.ssss.com/bbb,20220305121018,20220305122104
⑧http://www.ssss.com/aaa,20220305121355,20220305122104
如上图,分别按照eventtime 和 processtime 进行统计处理
按5分钟粒度统计得到以下数值(eventtime )
00-05 | 06-10 | 11-15 | |
aaa | 3 | 0 | 1 |
bbb | 0 | 3 | 0 |
ccc | 0 | 1 | 0 |
按5分钟粒度统计得到以下数值(processtime)
00-05 | 06-10 | 11-15 | 16-20 | |
aaa | 0 | 2 | 1 | 1 |
bbb | 0 | 1 | 1 | 3 |
ccc | 0 | 0 | 0 | 1 |
可以很明显的看出来,按照业务逻辑,eventtime统计的数值是我们需要的,而按照processtime时间进行计算得到的数值是存在问题的。因此,这时候就需要用到了flink的 watermark。
env.setStreamTimeCharacteristic(TimeCharacteristic.EventTime);
//设置eventtime字段
DataStream> streamResult= sourceStream.assignTimestampsAndWatermarks(new AscendingTimestampExtractor>() {
@Override
public long extractAscendingTimestamp(Tuple2 element) {
String[] str = element.f1.split("|");
return Long.parseLong(str[1]);
}
});
SingleOutputStreamOperator
time5Min = streamResult.keyBy(0).window(EventTimeSessionWindows.withGap(Time.seconds(300))).allowedLateness(Time.seconds(300)).reduce(new FlowStatReduce()).flatMap(new FlowStatImport("STAT_5MIN")).name("5MIN");
这里用到了
(1)EventTimeSessionWindows,SessionWindos触发会依据数据的EventTime来触发,程序会依据数据流入的最新的时间来当作当前时间,以此为依据来触发以满足的时间间隔的数据分区。
(2)allowedLateness 设定窗口允许的延迟,正常情况下窗口触发计算完成之后就会被小会,但是设定了允许延迟之后,窗口会等待allowedLateness的时长后再销毁。在该区间内的迟到数据任然可以进入窗口中,并触发新的计算。