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. C# DataSet与DataTable的区别和用法 ---转载

    C# DataSet与DataTable的区别和用法 转载:https://www.cnblogs.com/liuyi-li/p/6340411.html DataSet是数据集,DataTable是 ...

  2. c++存储区域

    来自:https://www.cnblogs.com/simonote/articles/3146038.html 在C++中,内存分成5个区,他们分别是堆.栈.自由存储区.全局/静态存储区和常量存储 ...

  3. OpenCV数字识别

    输入命令: conda install opencv 返回信息:

  4. 第1节 storm编程:7、并行度分析以及如何解决线程安全问题

    storm其实就是一个多进程与多线程的框架 开多个进程:分配到的资源更多 开多个线程:执行的速度更快 设置进程个数以及线程个数 ==================================== ...

  5. python实现PCA算法原理

    PCA主成分分析法的数据主成分分析过程及python原理实现 1.对于主成分分析法,在求得第一主成分之后,如果需要求取下一个主成分,则需要将原来数据把第一主成分去掉以后再求取新的数据X’的第一主成分, ...

  6. TeX 常用命令记录

    常用: $a_{i}^{2}$    a_{i}^{2} $\sqrt x$     $\sqrt[n] x$     \sqrt[n] x $\frac{1+2}{3+4}$ 重音符号: $\hat ...

  7. 四 Hibernate的一级缓存&事务管理及其配置

    持久态对象: 自动更新数据库,原理是一级缓存. 缓存:是一种优化的方式,将数据存入内存,从缓存/内存中获取,不用通过存储源 Hibernate框架中提供了优化手段:缓存,抓取策略 Hibernate中 ...

  8. Eclipse创建一个动态maven项目详细步骤

    新建maven项目,new一个Dynamic Web Project 项目 输入完项目名直接finish 配maven,右键项目configure,选择Convert to Plug-in Proje ...

  9. JavaScript 字符编码

    JavaScript 字符编码 JavaScript 遵循 Unicode 字符编码规则.Unicode 字符集中每个字符使用 2 个字节来表示,这意味着用户可以使用中文来命名 Java)Script ...

  10. swoole之创建子进程

    一.代码 <?php /** * 进程就是正在运行的程序的一个实例 * 比如,在某个终端中执行一个PHP脚本,可以认为就是开启了一个进程,会有对应的进程id(pid) * * swoole进程与 ...