这是我参与「第四届青训营 」笔记创作活动的第5天。
在之前的笔记中,已对流计算基础、rpc、thrift、Flink 等做了介绍。俗话说温故而知新,今天在学习了DataFlow 论文研读后,又温习了前期的课程内容,在整理笔记的过程中又有了许多新的收获,为项目开发实现提供了参考。
事件时间和处理时间
流计算过程中,数据源源不断到来,虽然我们希望数据总是能被实时地处理,但是数据却不可避免受到传输过程中的各种因素导致延迟。
下面引出了两种时间的概念:
- 事件时间(event time):事件真实发生、数据产生的时间
- 处理时间(process time):数据被处理的时间
可以看到处理时间一般晚于事件时间。ideal 的情况下,差距越小越好。
Watermark(水位线)
由于数据可能乱序和迟到,我们在处理数据的过程中就需要定义一个时间度量,用于判断当前event time的时间。
Watermark,定义为当前系统认为的事件发生所在的真实时间。它可以由当前系统能看到的数据的事件时间计算而来,如减去一个固定的delay,来表示可以容忍多长时间的乱序。
当watermark 更新到某个时间值时,我们可以认为所有时间戳小于watermark的数据都已经到达了。
对于再来的迟到数据,将会另做处理,如输出到另外的数据管道或直接丢弃。
传递watermark:根据上游的最小值计算自己的 watermark,然后给下游传递。
Window(窗口)
为啥需要window:对于流计算中的无限数据集,对数据做有限块的切割以后续进行处理。对于聚合类操作比较有用,例如:统计在过去的1分钟内有多少用户点击了网页。
window 机制是 Streaming 到 Batch 的一个桥梁。
窗口类型
三种基本类型:滚动窗口,滑动窗口,会话窗口
- 滚动窗口:创建时指定窗口大小(时间跨度固定)。窗口之间的数据没有重叠。
- 滑动窗口。创建时指定窗口大小和滑动周期。窗口之间的数据可以重叠。滚动窗口可以视为滑动周期与窗口大小相等的滑动窗口。
- 会话窗口。创建时指定超时时间。如果新输入数据的事件时间与先前数据的事件时间相比超过了超时时间,则新输入数据属于新的会话窗口;如果没有超过超时时间,则它形成的窗口与先前的窗口合并。是一个动态 merge的过程,与业务结合的比较紧密。
窗口触发器
触发器(Trigger)决定了一个窗口何时能够被计算或清除。
触发策略有多种选择,如“当窗口中的元素数量大于4”时,或“当水位线越过窗口结束时”等。
现有的计算框架采用了Watermark作为窗口计算的触发器。当水位线越过了窗口结束时间,窗口则关闭和进行计算。
EMIT触发: 在window没有结束的时候,允许提前把window计算的部分结果输出。一个不断变化的结果。
Evictor: 在触发器触发后 & 应用函数之前和/或之后 从窗口中删除元素。
迟到数据
迟到数据的定义:晚于 watermark 到达,但可能它还在窗口中。
处理迟到数据的方法:
- 丢弃:flink 的默认处理方式
- Allow lateness(允许迟到):修正之前的结果,retract
- SideOutput(侧输出流):打tag,然后根据业务情况具体处理
计算模式
增量计算 vs 全量计算
数据到来时的两种计算模式:
- 增量计算:每条数据到来时,直接计算;只保存计算结果,如 sum、reduce、aggregate;
- 全量计算:数据到来时保存在窗口中,window 触发时一起计算;
增量计算模型
增量计算模型定义了当窗口计算之后内容如何处理。三种策略:
- 丢弃:触发计算后,窗口内容被丢弃,后续的计算结果与先前的计算结果没有关系。
- 累积:触发计算后,窗口内容被完整保留在持久化状态中,后续的计算结果会修正先前的结果。
- 累积并撤回:触发计算后,在累积语义的基础上,输出结果的拷贝也被存储在了持久化状态中。当之后窗口再次触发计算时,会先引发先前结果的撤回,然后新的计算结果再发往下游。
示例
- 正确性、实时性、成本
- 批流如何统一
-
全局窗口,周期触发,累积模式
-
全局窗口,周期触发,丢弃模式
-
全局窗口,基于计数,丢弃模式
-
经典批处理
-
固定窗口,批处理
-
固定窗口,微批处理
-
固定窗口,流处理
-
固定窗口,流处理,多种触发方式(watermark)