Apache Flink:流处理中Window的概念

Apache Flink–DataStream–Window

什么是Window?有哪些用途?
下面我们结合一个现实的例子来说明。

我们先提出一个问题:统计经过某红绿灯的汽车数量之和?
假设在一个红绿灯处,我们每隔15秒统计一次通过此红绿灯的汽车数量,如下图:
这里写图片描述
可以把汽车的经过看成一个流,无穷的流,不断有汽车经过此红绿灯,因此无法统计总共的汽车数量。但是,我们可以换一种思路,每隔15秒,我们都将与上一次的结果进行sum操作(滑动聚合),如下:
这里写图片描述
这个结果似乎还是无法回答我们的问题,根本原因在于流是无界的,我们不能限制流,但可以在有一个有界的范围内处理无界的流数据。

因此,我们需要换一个问题的提法:每分钟经过某红绿灯的汽车数量之和?
这个问题,就相当于一个定义了一个Window(窗口),window的界限是1分钟,且每分钟内的数据互不干扰,因此也可以称为翻滚(不重合)窗口,如下图:
这里写图片描述
第一分钟的数量为8,第二分钟是22,第三分钟是27。。。这样,1个小时内会有60个window。

再考虑一种情况,每30秒统计一次过去1分钟的汽车数量之和:
这里写图片描述
此时,window出现了重合。这样,1个小时内会有120个window。

扩展一下,我们可以在某个地区,收集每一个红绿灯处汽车经过的数量,然后每个红绿灯处都做一次基于1分钟的window统计,即并行处理:
这里写图片描述

通常来讲,Window就是用来对一个无限的流设置一个有限的集合,在有界的数据集上进行操作的一种机制。window又可以分为基于时间(Time-based)的window以及基于数量(Count-based)的window。

Flink DataStream API提供了Time和Count的window,同时增加了基于Session的window。同时,由于某些特殊的需要,DataStream API也提供了定制化的window操作,供用户自定义window。

下面,主要介绍Time-Based window以及Count-Based window,以及自定义的window操作,Session-Based Window操作将会在后续的文章中讲到。

1、Time-Based Window
1.1、Tumbling window(翻滚)
此处的window要在keyed Stream上应用window操作,当输入1个参数时,代表Tumbling window操作,每分钟统计一次,此处用scala语言实现:

// Stream of (sensorId, carCnt)
val vehicleCnts: DataStream[(Int, Int)] = ...

val tumblingCnts: DataStream[(Int, Int)] = vehicleCnts
  // key stream by sensorId
  .keyBy(0) 
  // tumbling time window of 1 minute length
  .timeWindow(Time.minutes(1))
  // compute sum over carCnt
  .sum(
  • 10
    点赞
  • 16
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
可以使用Flink的DataStream API来实现处理程序,以下是一个简单的代码示例: ```java import org.apache.flink.api.java.functions.KeySelector; import org.apache.flink.streaming.api.datastream.DataStream; import org.apache.flink.streaming.api.environment.StreamExecutionEnvironment; import org.apache.flink.streaming.api.functions.windowing.WindowFunction; import org.apache.flink.streaming.api.windowing.assigners.TumblingProcessingTimeWindows; import org.apache.flink.streaming.api.windowing.windows.TimeWindow; import org.apache.flink.streaming.api.windowing.windows.Window; import org.apache.flink.util.Collector; public class WordCount { public static void main(String[] args) throws Exception { StreamExecutionEnvironment env = StreamExecutionEnvironment.getExecutionEnvironment(); // 从socket读取数据 DataStream<String> stream = env.socketTextStream("localhost", 9999); // 将每行数据按空格拆分成单词 DataStream<String> words = stream.flatMap((String line, Collector<String> out) -> { for (String word : line.split(" ")) { out.collect(word); } }); // 对每个单词进行计数,生成(word, count)格式的二元组 DataStream<Tuple2<String, Integer>> counts = words.keyBy((KeySelector<String, String>) value -> value) .window(TumblingProcessingTimeWindows.of(Time.seconds(5))) .apply(new WindowFunction<String, Tuple2<String, Integer>, String, TimeWindow>() { @Override public void apply(String key, TimeWindow window, Iterable<String> input, Collector<Tuple2<String, Integer>> out) { int count = 0; for (String word : input) { count++; } out.collect(new Tuple2<>(key, count)); } }); // 打印计数结果 counts.print(); env.execute("Word Count"); } } ``` 上述代码,首先从socket读取数据,然后将每行数据按空格拆分成单词。接着对每个单词进行计数,生成二元组。最后打印计数结果。这里使用了Flink的窗口操作,每隔5秒钟计算一次窗口内单词出现次数的总和。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值