Bootstrap

flink将窗口增量聚合算子和窗口全量聚合算子连用

在flink中,开窗后的聚合方式有两种,增量聚合和全量聚合,前者处理速度快,不积压数据,但是拿不到窗口中全量的信息,后者积压数据但是能拿到窗口内全量的数据。两者各有利弊。

因此滚动聚合窗口和全量聚合窗口连用,即利用了滚动聚合性能好,资源占用率低的优点,又能拥有全量窗口函数中的窗口信息。

此时的增量聚合函数中只每次处理1条数据,当所有的数据在增量函数完成后,最后再经过一次窗口函数,因此窗口全量聚合算子中只有一条reduce聚合后的数据。

winodw().reduce(ReduceFunction(),ProcessWindowFunction())

// 开窗,Tumbling(10s)
        SingleOutputStreamOperator<TrafficPageViewBean> unionWateredKeyedReduced = unionWateredKeyed.window(TumblingEventTimeWindows.of(Time.seconds(10)))
                .reduce(new ReduceFunction<TrafficPageViewBean>() {
                    @Override
                    public TrafficPageViewBean reduce(TrafficPageViewBean t0, TrafficPageViewBean t1) throws Exception {
                        t1.setSvCt(t1.getSvCt() + t0.getSvCt());
                        t1.setPvCt(t1.getPvCt() + t0.getPvCt());
                        t1.setDurSum(t1.getDurSum() + t0.getDurSum());
                        t1.setUjCt(t1.getUjCt() + t0.getUjCt());
                        t1.setUvCt(t1.getUvCt() + t0.getUvCt());
                        return t1;
                    }
                }, new ProcessWindowFunction<TrafficPageViewBean, TrafficPageViewBean, Tuple4<String, String, String, String>, TimeWindow>() {
                    @Override
                    public void process(Tuple4<String, String, String, String> tp4, Context context, Iterable<TrafficPageViewBean> iterable, Collector<TrafficPageViewBean> collector) throws Exception {
                        /*
                            将滚动聚合窗口和全量聚合窗口连用,即利用了滚动聚合性能好,资源占用率低的优点,又能拥有全量窗口函数中的窗口信息
                            此时的迭代器中只有1条:当所有的数据reduce完成后在经过一次窗口函数,因此窗口函数中只有一条reduce聚合后的数据
                         */
                        TrafficPageViewBean reduced = iterable.iterator().next();

                        // 组装窗口字段
                        long start = context.window().getStart();
                        long end = context.window().getEnd();

                        reduced.setStt(DateFormatUtils.toYmdHms(start));
                        reduced.setEdt(DateFormatUtils.toYmdHms(end));
                        // 置于一个新的ts作为去重比较字段
                        reduced.setTs(System.currentTimeMillis());
                        // 发送出去!!!
                        collector.collect(reduced);
                    }
                });

;