流处理架构进行计数

l 事件流由消息传输系统提供。
l Flink会以时间为单位将事件流分割成一批批任务(称作窗口)。
l 因此我们在为任务进行进行分组时,只需要对窗口的定义即可。
l 重新运行程序只需要在消息传输层重播即可。
流处理区别与批处理最主要的两点是:
1. 数据流不必人为切割为文件。
2. 时间的定义十分明确。

流处理系统中的批处理

一般而言使用微批处理来实现批处理,即在shuffle阶段把多个时间的缓冲发送,而不是单个事件。
流处理中的批处理必须符合两点要求:
3. 批处理只作为提高系统性能的机制。
4. 批处理必须完全独立于流处理运行部分。

时间概念

在流处理的过程中会定义时间,不同的时间定义适用于不同的场景。
事件时间:事件实际发生的时间,用于标记事件。适合准确性要求高的场景。
处理时间:事件被机器处理的时间。适合有误差也没事的快速处理场景。
事件时间:发生了什么事
处理时间:什么时候发生的
第四章 对时间的处理 - 图1
还有一个摄取时间(进入时间),记录时间进入流处理框架的时间,不经常用。

窗口

窗口是将事件按照不同特征(时间等)分组的机制。

时间窗口

支持滚动与滑动两种不同的窗口类型。采用事件时间的时间窗口会在收到水印后触发。

滚动窗口

计算一定时间a内的数据,算完了进入下一个窗口。
stream.timeWindow(Time.minutes(1)) // 1分钟滚动窗口

第四章 对时间的处理 - 图2

滑动窗口

虽然同样计算一定时间a内的数据,但是会在指定的时间b提前计算,算完了就进入下一个窗口。而不是等a时间到了再计算。
stream.timeWindow(Time.minutes(1), Time.seconds(30)) // 1分钟滑动窗口,每隔30s滑动一次

第四章 对时间的处理 - 图3

计数窗口

分组依据不是时间而是元素的数量,同样也有滚动和滑动两种。
但是和时间不一样,窗口在满足数量后才会关闭,因此需要配合时间窗口才能保证窗口的内存不被浪费。
stream.countWindow(4) // 滚动 stream.countWindow(4, 2) // 滑动

会话窗口

类似session的概念。在用户交互时就是活动阶段。
Flink中会话非活动时长超时就认为会话结束。
stream.window(SessionWindows.withGap(Time.minutes(5))) // 非活动超过5分钟会话结束

可以通过基本的开窗机制自定义更复杂的窗口形式

时空穿梭

若要重新处理数据,就必须使用事件时间,因为处理时间从定义上会导致结果不一致。

水印

l 因为流数据很多时候是乱序的,因此在处理各种窗口的时候就有一个问题:如何知道这是窗口的最后一个数据?
l 在发送数据时就会添加水印,当收到最后一个水印标记时,我们就认为数据全部收到了。因此在最后一个水印迟到的情况下,处理效率会受到影响。
l 因此我们需要保证水印是有序的,这需要用户自己定义确保,或者使用一个监控事件流学习迟到规律构建水印生成模型。
l 水印迟到太久,速度就会变慢,我们可以提前输出近似结果,但这样准确性就无法保证。如果到了太早,就会漏掉很多数据,得到错误答案。