Flink(四)--DataStream的窗口计算

flink根据上游数据集是否为KeyedStream类型(将数据集按照Key分区),对应的Windows Assigner也会有所不同。上游数据集如果是KeyedStream类型,则调用DataStream API的windows()方法来指定Windows Assigner,数据会根据Key在不同的Task实例中并行分别计算,最后得出针对每个Key的统计结果。如果是Non-Keyed类型,则调用WindowsAll()方法来指定Windows Assigner,所有的数据都会在窗口算子中路由到一个Task中计算,并得到全局统计结果。

flink支持两种类型的窗口,一种是基于时间的窗口,一种是基于数量的窗口。

基于时间的窗口可分为四大类:滚动窗口(Tumbling Windows)、滑动窗口(Sliding Windows)、会话窗口(Session Windows)、全局窗口(Global Windows)。

(1)滚动窗口:根据固定时间或大小进行切分,且窗口和窗口之间的元素互不重叠。

        final StreamExecutionEnvironment env = StreamExecutionEnvironment.getExecutionEnvironment();
        Properties props = new Properties();
        props.put("bootstrap.servers", "kafka:9092");
        props.put("group.id", "test_flink");

        DataStream<String> input = env.addSource(new FlinkKafkaConsumer010<String>
                ("test", new SimpleStringSchema(), props));
        SingleOutputStreamOperator<Tuple2<String, String>> map = input.map(new MapFunction<String, Tuple2<String, String>>() {
            @Override
            public Tuple2<String, String> map(String value) throws Exception {
                String[] strs = value.split(",");
                return new Tuple2<>(strs[0], strs[1]);
            }
        });

        WindowedStream<Tuple2<String, String>, Tuple, TimeWindow> window = map.keyBy(0).window(TumblingProcessingTimeWindows.of(Time.seconds(10)));
        SingleOutputStreamOperator<Tuple2<String, String>> process = window.process(new ProcessWindowFunction<Tuple2<String, String>, Tuple2<String, String>, Tuple, TimeWindow>() {
            @Override
            public void process(Tuple tuple, Context context, Iterable<Tuple2<String, String>> elements, Collector<Tuple2<String, String>> out) throws Exception {
                Iterator<Tuple2<String, String>> iterator = elements.iterator();
                StringBuffer sb = new StringBuffer();
                String key = null;
                while (iterator.hasNext()){
                    Tuple2<String, String> ele = iterator.next();
                    if (key == null){
                        key = ele.f0;
                    }
                    sb.append(ele.f1);
                }
                out.collect(new Tuple2<String,String>(key,sb.toString()));
            }
        });
        process.print();

kafka输入:

程序输出:

上面是用的TumblingProcessTimeWindows类,也可以

env.setStreamTimeCharacteristic(TimeCharacteristic.ProcessingTime);
WindowedStream<Tuple2<String, String>, Tuple, TimeWindow> window = map.keyBy(0).timeWindow(Time.seconds(10));

效果是一样的。

如果想使用事件时间,需要指定watermark和timestamp。这篇文章解释的非常清楚。感谢这位作者。

https://blog.csdn.net/xu470438000/article/details/83271123

除了指定watermark和timestamp之外,其他逻辑和上面的代码基本相同。

(2)滑动窗口:允许窗口数据发横重叠。滚动窗口可以看做是窗口大小与滑动步长相等的特殊滑动窗口。

WindowedStream<Tuple2<String, String>, Tuple, TimeWindow> window = map.keyBy(0).window(SlidingProcessingTimeWindows.of(Time.seconds(10),Time.seconds(5)));

(3)会话窗口:主要用于将某段时间内活跃度较高的数据聚合成一个窗口进行计算。窗口的触发条件是Session Gap,是指在规定的时间内如果没有数据进入窗口,那么就认为窗口结束,触发窗口进行计算。

WindowedStream<Tuple2<String, String>, Tuple, TimeWindow> window = map.keyBy(0).window(ProcessingTimeSessionWindows.withGap(Time.seconds(10)));

(4)全局窗口:窗口没有起始时间与结束时间,需要借助Triger来触发计算。

基于数量的窗口包括滚动窗口和滑动窗口。

滚动窗口:

WindowedStream<Tuple2<String, String>, Tuple, GlobalWindow> window = map.keyBy(0).countWindow(5);

滑动窗口:

WindowedStream<Tuple2<String, String>, Tuple, GlobalWindow> window = map.keyBy(0).countWindow(5,2);

基于数量的窗口本质上是一种全局窗口,触发条件就是窗口中的元素数量是否等于用户传入的参数。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值