技术13期:一文读懂Flink的流式处理及窗口理解

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

- 完 -

感兴趣的朋友记得关注公众号:普适极客噢

猜你喜欢

转载自blog.csdn.net/PUSHIAI/article/details/107465368