声明: 1. 本文为我的个人复习总结, 并非那种从零基础开始普及知识 内容详细全面, 言辞官方的文章
2. 由于是个人总结, 所以用最精简的话语来写文章
3. 若有错误不当之处, 请指出
时间语义:
EventTime:
在1.12版本中被设置成了默认
是事件的产生时间, 什么时候进行处理都一样
ProcessingTime
是Flink真正处理这条数据时的时间
IngestionTime:
是数据进入到Flink的时间
Watermark:
是为了解决乱序
是事件时间时才有意义, 是处理时间时没意义
是计数窗口时, 也没意义
数据乱序问题:
由于网络、分布式等原因导致数据乱序, 先产生的事件未必先到来,
这样我们不能明确数据是否全部到位, 但又不能无限期的等下去
此时要有个机制来保证一个特定的时间后, 必须得去触发window去进行计算了
解决方案:
这个机制就是Watermark, 即Watermark就是为了容忍一定程度的迟到数据, 延长窗口的终止时间, 是一种延迟触发机制
Watermark 是用于处理乱序事件的, 通常结合window来实现
特点:
-
分区内的
watermark
水位线=当前分区遇到的最大时间
-延迟时间
-
分区间watermark的传递规则:
下游分区将获得的上游所有分区中最小的那个watermark 设为当前分区的watermark(还要对比上一次的watermark, 进行min{ }操作);
每个分区watermark的初始值是Long.MIN_VALUE
-
只要watermark没有达到窗口关闭时间, 那么不管现实中的时间推进了多久都不会触发关闭窗口
-
窗口范围左闭右开
案例:
窗口1是 [1s,5s), 窗口2是 [6s,10s), watermark延迟时间设置为2s:
-
7s的事件对应的watermark是5s, 触发窗口1的计算
-
12s的事件的watermark是10s, 触发窗口2的计算
多个窗口是可能同时存在的
关于允许迟到时间:
- .assignTimestampsAndWatermarks(WatermarkStrategy<T> strategy) 是多等两秒后才结束窗口进行计算
- .allowedLateness(Time.minutes(1)) 是时间到了先进行直接计算, 在后续一分钟内如果还有数据到来, 会再次触发计算(第一次已经计算过的数据, 在这次也得进行重新计算)
- ctx.output(outputTag, value) 当迟到数据被
所有窗口
都不接收时, 才放到侧输出流, 后续单独处理
API-指定watermark字段&处理策略:
dataStream.assignTimestampsAndWatermarks(new BoundedOutOfOrdernessTimestampExtractor<SensorReading>(Time.seconds(1)) {
@Override
public long extractTimestamp(SensorReading element) {
return element.getTimestamp( ) * 1000L;
}
});
// BoundedOutOfOrdernessTimestampExtractor 是当作有乱序数据来处理
// AscendingTimestapExtractor 是当作升序数据来处理, 认为没乱序数据, 即没有延迟时间
// BoundedOutOfOrdernessTimestampExtractor 和 AscendingTimestapExtractor 都是AssignerWithPeriodicWatermarks 的子实现类
AssignerWithPeriodicWatermarks:
周期性
的将 watermark 插入到流中, 默认周期是200ms
AssignerWithPunctuatedWatermarks:
每来一个数据, 在重写的checkAndGetNextWatermark方法里, 就手动给watermark赋值, 也可以不赋值直接返回为null
这两个接口都继承于TimestampAssigner接口