Apache Flink是一个框架和分布式大数据处理引擎,可对有界数据流和无界数据流进行有状态计算。可部署在各种集群环境,对各种大小的数据规模进行快速计算。
Flink基本概念
流处理:特点是无限、实时,无需针对整个数据集执行操作,而是通过对系统传输的每个数据项执行操作,一般用于实时统计。
有界数据流:有明确定义的开始和结束,可以在执行任何计算之前通过获取所有数据来处理有界流,处理有界流不需要有序获取,因为可以始终对有界数据集进行排序,有界流的处理也称为批处理。
无界数据流:有一个开始但是没有结束,它们不会在生成时终止并提供数据,必须连续处理无界流,也就是必须在获取后立即处理event。
处理无界数据通常要求以特定顺序(如事件发生的顺序)获取event,以便能够推断结果完整性。
个人认为,与Spark相比,Spark在生态总体上更加完善,在机器学习的集成以及易用程度更为领先,但Flink在流计算上有着明显优势且其核心架构和模型更为灵活。
随着阿里巴巴在2019年初将其内部版本”Blink”开源且不断推进和加深Flink社区的发展,以及目前市场上实时指标处理、实时数仓等需求的增多。
未来在大数据方向,机器学习逐渐从批处理、离线学习向实时处理和在线学习发展;在图计算领域,反欺诈事件都是实时的、持续不断发生,图计算也在变得实时化。
相信Flink日后的发展势头也将越发迅猛。
什么是Window?
在流处理应用中,数据是连续不断的,因此我们不可能等到所有数据都到了才开始处理。当然我们可以每来一条消息就处理一次,但有时需要做一些聚合类的处理。
例如:在过去的1分钟内有多少用户点击了网页。
在这种情况下,必须定义一个窗口,用来收集最近一分钟内的数据,并对这个窗口内的数据进行计算。
举一个简单的场景来形象地理解不同窗口的概念。
假设,淘宝网会记录每个用户每次购买的商品个数,我们要做的是统计不同窗口中用户购买商品的总数。
下图给出了几种经典的窗口切分概述图:
上图中,raw data stream代表用户的购买行为流,圈中的数字代表该用户本次购买的商品个数,事件是按时间分布的,所以可以看出事件之间是有time gap的。
窗口类型
Flink提供了上图中所有的窗口类型,下面来逐一介绍。
- Time Window
是根据时间对数据流进行分组的,Flink提供了三种时间的概念,分别是event time(事件时间:事件发生的事件),ingesting time(摄取时间:事件进入流处理系统的时间),processing time(处理时间:消息被计算处理的时间)。
Flink中窗口机制和时间类型是完全解耦的,也就是说当需要改变时间类型时,不需要更改窗口逻辑相关的代码。
- Tumbling Window
将数据依据固定的窗口长度对数据进行切片。
适用场景:适合做BI统计等。
如上图,我们需要统计每一分钟中用户购买的商品的总数,需要将用户的行为事件按每一分钟进行切分,这种切分被称为翻滚时间窗口。
翻滚窗口能将数据流切分成不重叠的窗口,每一个事件只能属于一个窗口。
通过DataStream API,可以这样实现:
// Stream of (userId, buyCnt)
val buyCnts: DataStream[(Int, Int)] = ...
val tumblingCnts: DataStream[(Int, Int)] = buyCnts
// key stream by userId
.keyBy(0)
// tumbling time window of 1 minute length
.timeWindow(Time.minutes(1))
// compute sum over buyCnt
.sum(1)
- Sliding Windows
滑动窗口由固定的窗口长度和滑动间隔组成。
适用场景:对最近一个时间段内的统计。
比如,每30s计算一次最近一分钟用户购买的商品总数。在滑动窗口中,一个元素可以对应多个窗口。
通过DataStream API,可以这样实现:
val slidingCnts: DataStream[(Int, Int)] = buyCnts
.keyBy(0)
// sliding time window of 1 minute length and 30 secs trigger interval
.timeWindow(Time.minutes(1), Time.seconds(30))
.sum(1)
- Session Window
由一系列事件组合一个指定时间长度的timeout间隙组成,类似于web应用的session,也就是一段时间没有接收到新数据就会生成新的窗口。
在这种用户交互事件流中,首先想到的是将事件聚合到会话窗口(一段用户持续活跃的周期),由非活跃的间隙分隔开。
比如,计算每个用户在活跃期间总共购买的商品数量,如果用户30s内没有活动则视为会话断开。
Session Window示例如下:
// Stream of (userId, buyCnts)
val buyCnts: DataStream[(Int, Int)] = ...
val sessionCnts: DataStream[(Int, Int)] = vehicleCnts
.keyBy(0)
// session window based on a 30 seconds session gap interval
.window(ProcessingTimeSessionWindows.withGap(Time.seconds(30)))
.sum(1)
总结:
Window是无界数据流处理的核心,它可以将一个无限的Stream拆分成有限大小的"buckets"桶,并在这些桶上进行计算操作。
相当于在无限的流上定义了一个有限的元素集合,这个集合可以是基于时间的、元素个数的、会话间隙等,同时Flink的DataStream API还提供了简洁的算子来满足常用的窗口操作。
参考资料:
https://www.slidestalk.com/FlinkChina
https://www.zhihu.com/people/ververica
- 完 -