1. 总览

    • Window 是flink处理无限流的核心,Windows将流拆分为有限大小的“桶”,我们可以在其上应用计算。

    • Flink 认为 Batch 是 Streaming 的一个特例,所以 Flink 底层引擎是一个流式引擎,在上面实现了流处理和批处理。

    • 而窗口(window)就是从 Streaming 到 Batch 的一个桥梁。

    • Flink 提供了非常完善的窗口机制。

    • 在流处理应用中,数据是连续不断的,因此我们不可能等到所有数据都到了才开始处理。

    • 当然我们可以每来一个消息就处理一次,但是有时我们需要做一些聚合类的处理,例如:在过去的1分钟内有多少用户点击了我们的网页。

    • 在这种情况下,我们必须定义一个窗口,用来收集最近一分钟内的数据,并对这个窗口内的数据进行计算。

    • 窗口可以是基于时间驱动的(Time Window,例如:每30秒钟)

    • 也可以是基于数据驱动的(Count Window,例如:每一百个元素)

    • 同时基于不同事件驱动的窗口又可以分成以下几类:

      • 翻滚窗口 (Tumbling Window, 无重叠)
      • 滑动窗口 (Sliding Window, 有重叠)
      • 会话窗口 (Session Window, 活动间隙)
      • 全局窗口 (略)
    • Flink要操作窗口,先得将StreamSource 转成WindowedStream

      Window操作 其作用
      Window Keyed Streaming → WindowedStream 可以在已经分区的KeyedStream上定义Windows,即K,V格式的数据。
      WindowAll DataStream → AllWindowedStream 对常规的DataStream上定义Window,即非K,V格式的数据
      Window Apply WindowedStream → AllWindowedStream AllWindowedStream → DataStream 将函数应用于整个窗口中的数据
      Window Reduce WindowedStream → DataStream 对窗口里的数据进行”reduce”减少聚合统计
      Aggregations on windows WindowedStream → DataStream 对窗口里的数据进行聚合操作: sum(), max(), min()
  2. Tumbling Window(翻滚窗口)

    • 翻滚窗口能将数据流切分成不重叠的窗口,每一个事件只能属于一个窗口

    • 翻滚窗具有固定的尺寸,不重叠。

    • 例图:

      • 代码

        package com.ronnie.flink.stream.window;
        
        import org.apache.flink.api.common.functions.MapFunction;
        import org.apache.flink.api.java.tuple.Tuple;
        import org.apache.flink.api.java.tuple.Tuple2;
        import org.apache.flink.streaming.api.datastream.DataStreamSource;
        import org.apache.flink.streaming.api.datastream.KeyedStream;
        import org.apache.flink.streaming.api.datastream.SingleOutputStreamOperator;
        import org.apache.flink.streaming.api.datastream.WindowedStream;
        import org.apache.flink.streaming.api.environment.StreamExecutionEnvironment;
        import org.apache.flink.streaming.api.windowing.time.Time;
        import org.apache.flink.streaming.api.windowing.windows.GlobalWindow;
        import org.apache.flink.streaming.api.windowing.windows.TimeWindow; import java.text.SimpleDateFormat;
        import java.util.Random; /**
        * 翻滚窗口:窗口不可重叠
        * 1、基于时间驱动
        * 2、基于事件驱动
        */
        public class TumblingWindow { public static void main(String[] args) {
        //设置执行环境,类似spark中初始化sparkContext
        StreamExecutionEnvironment env = StreamExecutionEnvironment.getExecutionEnvironment(); env.setParallelism(1); DataStreamSource<String> dataStreamSource = env.socketTextStream("ronnie01", 9999); SingleOutputStreamOperator<Tuple2<String, Integer>> mapStream = dataStreamSource.map(new MapFunction<String, Tuple2<String, Integer>>() {
        @Override
        public Tuple2<String, Integer> map(String value) throws Exception { SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS"); long timeMillis = System.currentTimeMillis(); int random = new Random().nextInt(10); System.out.println("value: " + value + " random: " + random + "timestamp: " + timeMillis + "|" + format.format(timeMillis)); return new Tuple2<String, Integer>(value, random);
        }
        }); KeyedStream<Tuple2<String, Integer>, Tuple> keyedStream = mapStream.keyBy(0); // 基于时间驱动,每隔10s划分一个窗口
        WindowedStream<Tuple2<String, Integer>, Tuple, TimeWindow> timeWindow = keyedStream.timeWindow(Time.seconds(10)); // 基于事件驱动, 每相隔3个事件(即三个相同key的数据), 划分一个窗口进行计算
        // WindowedStream<Tuple2<String, Integer>, Tuple, GlobalWindow> countWindow = keyedStream.countWindow(3); // apply是窗口的应用函数,即apply里的函数将应用在此窗口的数据上。
        timeWindow.apply(new MyTimeWindowFunction()).print();
        // countWindow.apply(new MyCountWindowFunction()).print(); try {
        // 转换算子都是lazy init的, 最后要显式调用 执行程序
        env.execute();
        } catch (Exception e) {
        e.printStackTrace();
        } }
        }
    • 基于时间驱动

      • 场景1:我们需要统计每一分钟中用户购买的商品的总数,需要将用户的行为事件按每一分钟进行切分,这种切分被成为翻滚时间窗口(Tumbling Time Window)。

        package com.shsxt.flink.stream.window;
        
        import org.apache.flink.api.java.tuple.Tuple;
        import org.apache.flink.api.java.tuple.Tuple2;
        import org.apache.flink.streaming.api.functions.windowing.WindowFunction;
        import org.apache.flink.streaming.api.windowing.windows.TimeWindow;
        import org.apache.flink.util.Collector; import java.text.SimpleDateFormat; public class MyTimeWindowFunction implements WindowFunction<Tuple2<String,Integer>, String, Tuple, TimeWindow> { @Override
        public void apply(Tuple tuple, TimeWindow window, Iterable<Tuple2<String, Integer>> input, Collector<String> out) throws Exception {
        SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS"); int sum = 0; for(Tuple2<String,Integer> tuple2 : input){
        sum +=tuple2.f1;
        } long start = window.getStart();
        long end = window.getEnd(); out.collect("key:" + tuple.getField(0) + " value: " + sum + "| window_start :"
        + format.format(start) + " window_end :" + format.format(end)
        ); }
        }
    • 基于事件驱动

      • 场景2:当我们想要每100个用户的购买行为作为驱动,那么每当窗口中填满100个”相同”元素了,就会对窗口进行计算。

        package com.ronnie.flink.stream.window;
        
        import org.apache.flink.api.java.tuple.Tuple;
        import org.apache.flink.api.java.tuple.Tuple2;
        import org.apache.flink.streaming.api.functions.windowing.WindowFunction;
        import org.apache.flink.streaming.api.windowing.windows.GlobalWindow;
        import org.apache.flink.util.Collector; import java.text.SimpleDateFormat; public class MyCountWindowFunction implements WindowFunction<Tuple2<String, Integer>, String, Tuple, GlobalWindow> { @Override
        public void apply(Tuple tuple, GlobalWindow window, Iterable<Tuple2<String, Integer>> input, Collector<String> out) throws Exception {
        SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS"); int sum = 0; for (Tuple2<String, Integer> tuple2 : input){
        sum += tuple2.f1;
        }
        //无用的时间戳,默认值为: Long.MAX_VALUE,因为基于事件计数的情况下,不关心时间。
        long maxTimestamp = window.maxTimestamp(); out.collect("key:" + tuple.getField(0) + " value: " + sum + "| maxTimeStamp :"
        + maxTimestamp + "," + format.format(maxTimestamp)
        );
        }
        }
  3. Sliding Window(滑动窗口)

    • 滑动窗口和翻滚窗口类似,区别在于:滑动窗口可以有重叠的部分。

    • 在滑窗中,一个元素可以对应多个窗口。

    • 例图:

    • 基于时间的滑动窗口

      • 场景: 我们可以每30秒计算一次最近一分钟用户购买的商品总数。
    • 基于事件的滑动窗口

      • 场景: 每10个 “相同”元素计算一次最近100个元素的总和.
    • 代码:

      package com.ronnie.flink.stream.window;
      
      import org.apache.flink.api.common.functions.MapFunction;
      import org.apache.flink.api.java.tuple.Tuple;
      import org.apache.flink.api.java.tuple.Tuple2;
      import org.apache.flink.streaming.api.datastream.DataStreamSource;
      import org.apache.flink.streaming.api.datastream.KeyedStream;
      import org.apache.flink.streaming.api.datastream.SingleOutputStreamOperator;
      import org.apache.flink.streaming.api.datastream.WindowedStream;
      import org.apache.flink.streaming.api.environment.StreamExecutionEnvironment;
      import org.apache.flink.streaming.api.windowing.time.Time;
      import org.apache.flink.streaming.api.windowing.windows.GlobalWindow;
      import org.apache.flink.streaming.api.windowing.windows.TimeWindow; import java.text.SimpleDateFormat;
      import java.util.Random; /**
      * 滑动窗口:窗口可重叠
      * 1、基于时间驱动
      * 2、基于事件驱动
      */
      public class SlidingWindow { public static void main(String[] args) {
      // 设置执行环境, 类似spark中初始化SparkContext
      StreamExecutionEnvironment env = StreamExecutionEnvironment.getExecutionEnvironment(); env.setParallelism(1); DataStreamSource<String> dataStreamSource = env.socketTextStream("ronnie01", 9999); SingleOutputStreamOperator<Tuple2<String, Integer>> mapStream = dataStreamSource.map(new MapFunction<String, Tuple2<String, Integer>>() {
      @Override
      public Tuple2<String, Integer> map(String value) throws Exception {
      SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS");
      long timeMillis = System.currentTimeMillis(); int random = new Random().nextInt(10);
      System.err.println("value : " + value + " random : " + random + " timestamp : " + timeMillis + "|" + format.format(timeMillis)); return new Tuple2<String, Integer>(value, random);
      }
      });
      KeyedStream<Tuple2<String, Integer>, Tuple> keyedStream = mapStream.keyBy(0); //基于时间驱动,每隔5s计算一下最近10s的数据
      // WindowedStream<Tuple2<String, Integer>, Tuple, TimeWindow> timeWindow = keyedStream.timeWindow(Time.seconds(10), Time.seconds(5));
      //基于事件驱动,每隔2个事件,触发一次计算,本次窗口的大小为3,代表窗口里的每种事件最多为3个
      WindowedStream<Tuple2<String, Integer>, Tuple, GlobalWindow> countWindow = keyedStream.countWindow(3, 2); // timeWindow.sum(1).print(); countWindow.sum(1).print(); // timeWindow.apply(new MyTimeWindowFunction()).print(); try {
      env.execute();
      } catch (Exception e) {
      e.printStackTrace();
      }
      }
      }
  4. Session Window(会话窗口)

    • 会话窗口不重叠,没有固定的开始和结束时间

    • 与翻滚窗口和滑动窗口相反, 当会话窗口在一段时间内没有接收到元素时会关闭会话窗口。

    • 后续的元素将会被分配给新的会话窗口

    • 例图:

    • 举例:

      • 计算每个用户在活跃期间总共购买的商品数量,如果用户30秒没有活动则视为会话断开。
    • 代码:

      package com.ronnie.flink.stream.window;
      
      import org.apache.flink.api.common.functions.MapFunction;
      import org.apache.flink.api.java.tuple.Tuple;
      import org.apache.flink.api.java.tuple.Tuple2;
      import org.apache.flink.streaming.api.datastream.DataStreamSource;
      import org.apache.flink.streaming.api.datastream.KeyedStream;
      import org.apache.flink.streaming.api.datastream.SingleOutputStreamOperator;
      import org.apache.flink.streaming.api.datastream.WindowedStream;
      import org.apache.flink.streaming.api.environment.StreamExecutionEnvironment;
      import org.apache.flink.streaming.api.windowing.assigners.ProcessingTimeSessionWindows;
      import org.apache.flink.streaming.api.windowing.time.Time;
      import org.apache.flink.streaming.api.windowing.windows.TimeWindow; import java.text.SimpleDateFormat;
      import java.util.Random; public class SessionWindow { public static void main(String[] args) { // 设置执行环境, 类似spark中初始化sparkContext StreamExecutionEnvironment env = StreamExecutionEnvironment.getExecutionEnvironment(); env.setParallelism(1); DataStreamSource<String> dataStreamSource = env.socketTextStream("ronnie01", 9999); SingleOutputStreamOperator<Tuple2<String, Integer>> mapStream = dataStreamSource.map(new MapFunction<String, Tuple2<String, Integer>>() {
      @Override
      public Tuple2<String, Integer> map(String value) throws Exception {
      SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS");
      long timeMillis = System.currentTimeMillis(); int random = new Random().nextInt(10); System.err.println("value : " + value + " random : " + random + " timestamp : " + timeMillis + "|" + format.format(timeMillis)); return new Tuple2<String, Integer>(value, random);
      }
      });
      KeyedStream<Tuple2<String, Integer>, Tuple> keyedStream = mapStream.keyBy(0); //如果连续10s内,没有数据进来,则会话窗口断开。
      WindowedStream<Tuple2<String, Integer>, Tuple, TimeWindow> window = keyedStream.window(ProcessingTimeSessionWindows.withGap(Time.seconds(10))); // window.sum(1).print(); window.apply(new MyTimeWindowFunction()).print(); try {
      env.execute();
      } catch (Exception e) {
      e.printStackTrace();
      }
      }
      }

Flink Window窗口机制的更多相关文章

  1. Flink(八)【Flink的窗口机制】

    目录 Flink的窗口机制 1.窗口概述 2.窗口分类 基于时间的窗口 滚动窗口(Tumbling Windows) 滑动窗口(Sliding Windows) 会话窗口(Session Window ...

  2. Apache Flink - Window

    Window: 在Streaming中,数据是无限且连续的,我们不可能等所有数据都到才进行处理,我们可以来一个就处理一下,但是有时我们需要做一些聚合类的处理,例如:在过去的1分钟内有多少用户点击了我们 ...

  3. Flink的窗口处理机制(一)

    一.为什么需要 window ? 在流处理应用中,数据是连续不断的,即数据是没有边界的,因此我们不可能等到所有数据都到了才开始处理.当然我们可以每来一个消息就处理一次,但是有时我们需要做一些聚合类的处 ...

  4. 一文搞懂Flink Window机制

    Windows是处理无线数据流的核心,它将流分割成有限大小的桶(buckets),并在其上执行各种计算. 窗口化的Flink程序的结构通常如下,有分组流(keyed streams)和无分组流(non ...

  5. [白话解析] Flink的Watermark机制

    [白话解析] Flink的Watermark机制 0x00 摘要 对于Flink来说,Watermark是个很难绕过去的概念.本文将从整体的思路上来说,运用感性直觉的思考来帮大家梳理Watermark ...

  6. flink的watermark机制你学会了吗?

    大家好,今天我们来聊一聊flink的Watermark机制. 这也是flink系列的的第一篇文章,如果对flink.大数据感兴趣的小伙伴,记得点个关注呀. 背景 ​ flink作为先进的流水计算引擎, ...

  7. Flink Window&Time 原理

    Flink 中可以使用一套 API 完成对有界数据集以及无界数据的统一处理,而无界数据集的处理一般会伴随着对某些固定时间间隔的数据聚合处理.比如:每五分钟统计一次系统活跃用户.每十秒更新热搜榜单等等 ...

  8. Android窗口机制分析与UI管理系统

    类图关系 在看Android的窗口机制之前,先看看其主要的类图关系以及层级之间的依赖与调用关系 1.window在当前的android系统的中的呈现形式是PhoneWindow (frameworks ...

  9. 【Android】窗口机制分析与UI管理系统

    类图关系 在看Android的窗口机制之前,先看看其主要的类图关系以及层级之间的依赖与调用关系 1.window在当前的android系统的中的呈现形式是PhoneWindow (frameworks ...

随机推荐

  1. 第1节 storm编程:4、storm环境安装以及storm编程模型介绍

    dataSource:数据源,生产数据的东西 spout:接收数据源过来的数据,然后将数据往下游发送 bolt:数据的处理逻辑单元.可以有很多个,基本上每个bolt都处理一部分工作,然后将数据继续往下 ...

  2. Mac的Terminal中无法使用mvim解决方案

    对于每个人来说,都会有特别喜欢的编辑器.对于很多热爱Unix/Linux的人来说,Vim/vi肯定是很熟悉的“编辑利器”了. 当然,对于Mac用户来说,肯定也不乏对Vim狂热的人.庆幸的是,Vim对M ...

  3. 针对小文件的spark wholeTextFiles()

    场景:推送过来的数据文件数量很多,并且每个只有10-30M的大小 spark读取hdfs一般都是用textfile(),但是对于这种情况,如果使用textFile默认产生的分区数将与文件数目一致,产生 ...

  4. layerui上传文件

    参考: http://www.layui.com/doc/modules/upload.html <1> 文件上传(以下函数必须要在js文件加载时执行) upload.render({ e ...

  5. 深入了解memcached

    一.memcached如何支持高并发 Memcached使用多路复用 I/O模型(如epoll.select等).传统阻塞 I/O中,系统可能会因为某个用户连接还没做好 I/O准备而一直等待,直到这个 ...

  6. jenkins -- 安装、任务构建

    一.jenkins是什么? Jenkins是一个开源的.提供友好操作界面的持续集成(CI)工具,起源于Hudson(Hudson是商用的),主要用于持续.自动的构建/测试软件项目.监控外部任务的运行( ...

  7. HDU - 1754 I Hate It (线段树点修改求最大值)

    题意:有N个学生M条操作,0<N<=200000,0<M<5000,要么查询某区间内学生的最高分,要么更改某学生的成绩. 分析:原理和线段树点修改求和类似. #include& ...

  8. 如何使用linux查看tomcat日志

  9. 浅谈JVM线程调度机制及主要策略

    在之前有说过线程,应该都知道,所谓线程就是进程中的一个子任务,一个进程有多个线程.今天的话主要就是谈一谈JVM线程调度机制.我们结合线程来说,当我们在做多线程的案例时,如一个经典案例,火车站卖票. * ...

  10. 剑指offer 按之字型顺序打印二叉树

    题目描述 请实现一个函数按照之字形打印二叉树,即第一行按照从左到右的顺序打印,第二层按照从右至左的顺序打印,第三行按照从左到右的顺序打印,其他行以此类推.   使用两个栈进行存储,我们在打印某一行节点 ...