名词概念
Streams(流)
-
unbounded stream
无限数据流
-
bounded stream
有限数据流
Time(时间)
时间是我们判断业务状态是否滞后,数据处理是否及时的重要依据。
有以下三个时间类型。
-
Event time
事件时间,事件在其设备上发生的时间。 数据的产生时间。 在数据最源头产生时带有时间戳,后面都需要用时间戳来进行运算
-
Ingestion time
注入时间,事件注入到 flink 的时间。
-
Processing time
事件处理时间,flink机器处理事件的时间。
window(窗口)
window是无界流数据处理的关键,flink将无界流拆分成无数个window。
窗口是有时间范围或数据量多少的,可以按照时间界定窗口时间范围,也可以按照事件数量界定窗口数据量多少。
窗口类型
-
滚动窗口(Tumbling Windows)
无重叠
-
滑动窗口(Sliding Windows)
有重叠
-
会话窗口(Session Windows)
无重叠,一段时间内没有接收到新数据就会就会生成新的窗口
- 全局窗口(Global Windows)
重叠分为两种:
时间重叠,指的是两个或多个窗口之间在时间上有重复。
事件重叠,指的是两个或多个窗口之间在事件上有重复。
窗口生命周期
收集数据开始:时间窗口,定时时间开始,并且第一个元素达到时。数量窗口,上一个窗口结束后,第一个元素到达。
收集数据结束:时间窗口,定时时间结束。数量窗口,事件数量达到用户设置的数量。
窗口的声明
watermark(水位线)
水位线是建立在window窗口之上的概念,狭义上指时间戳。可以想象一副场景,数据在管道中流动,有一条线把数据流分成了两部分,水位线就是用来截断数据的那根线。
watermark与窗口
如果所有事件都能100%在eventTime时刻到达,也就是事件生产完就到达处理,直接用窗口就好了,不需要水位线。
时间类窗口的目的就是为了收集周期内的事件,而事件偏偏是不完美的,即窗口内收的事件不在一个时间周期内。
水位线就是框架端提供了一种办法,可以把那些业务上认为太晚的事件给丢弃掉,这样保证了时效性,也增加了正确性,即时间窗口周期内处理的事件在eventTime维度上更加集中。
水位线 = 窗口内所有数据最大的eventTime - 用户设置的阈值
watermark生成流程
在窗口内的所有数据的事件时间中找到最大的时间Tmax。
用最大的时间Tmax减去用户设置的水位线阈值threshold,即watermark水位线时间再过滤一遍数据:丢弃掉比水位线时间小的更老的事件丢弃掉,保留比水位线以上更新的数据。
水位线阈值的设置
往往按照业务需要或者经验。
比如我认为我已经收到了最新T1的数据,比T1更早的时间点T2以前的数据即使过来了也不需要处理了,那么阈值就可以设置为T1-T2。
watermark作用
用于对窗口迟到数据的处理,eventTime小于(早于)watermark的数据不再处理。
换种说法”watermark是用于处理乱序事件的“也是成立的。
watermark时间戳特点
本质上水位线就是一个时间戳,有以下两个特点
动态:随着窗口一个接一个生成,watermark水位线的时间戳也是不断更新。
单调性:watermark不断更新,随着接收到的事件总体上越来越新,是一个比一个大(新)
watermark代码
如下代码:先声明水位线,再设置窗口。
val env = StreamExecutionEnvironment.getExecutionEnvironment
env.setStreamTimeCharacteristic(TimeCharacteristic.EventTime)
val stream: DataStream[MyEvent] = env.readFile(
myFormat, myFilePath, FileProcessingMode.PROCESS_CONTINUOUSLY, 100,
FilePathFilter.createDefaultFilter())
val withTimestampsAndWatermarks: DataStream[MyEvent] = stream
.filter( _.severity == WARNING )
.assignTimestampsAndWatermarks(new MyTimestampsAndWatermarks())
withTimestampsAndWatermarks
.keyBy( _.getGroup )
.timeWindow(Time.seconds(10))
.reduce( (a, b) => a.add(b) )
.addSink(...)
class MyTimestampsAndWatermarks implements AssignerWithPeriodicWatermarks {
long maxOutOfOrderness = 6000;
private long currentMaxTimestamp;
@Override
public long extractTimestamp(Object element, long previousElementTimestamp) {
long createtime = 0L;
if (element != null) {
try {
createtime = JSONObject.parseObject((String) element).getLong("createTime");
System.out.println("extrac" + createtime);
} catch (Exception e) {
e.printStackTrace();
}
}
currentMaxTimestamp = Math.max(createtime, currentMaxTimestamp);
return createtime;
}
@Nullable
@Override
public Watermark getCurrentWatermark() {
System.out.println("watermark" + (currentMaxTimestamp - maxOutOfOrderness));
return new Watermark(currentMaxTimestamp - maxOutOfOrderness);
}
}
API
SQL / Table API
DataStream API
ProcessFunction
应用场景
Data Pipeline (管道)
- 实时数仓
- 实时搜索
Data Analytics(分析)
Batch Analytics 和 Streaming Analytics
主要针对离线与实时报表
Data Driven(分析)
风控系统预警,处理各种各样复杂的规则
参考
Apache Flink 零基础入门(一):基础概念解析
flink watermark介绍
Structured Streaming 之 Watermark 解析(虽然是spark的,也建议看看)
Flink 调试watermark & allowedLateness
零基础学Flink:Window & Watermark