目录

Count Window

Time Window

Session Window

窗口聚合 

增量聚合

全量聚合


Flink有3个内置Window

  • Count Window 以事件数量驱动
  • Time Window  以时间驱动
  • Session Window 以会话间隔驱动

Count Window

计数窗口,采用事件数量作为窗口处理依据。计数窗口分为滚动和滑动两类,使用keyedStream.countWindow实现计数窗口定义。

  • Tumbling Count Window 滚动计数窗口 例子:以用户分组,当每位用户有3次付款事件时计算一次该用户付款总金额。下图中“消息A、B、C、D”代表4位不同用户,我们以A、B、C、D分组并计算金额。
/** 每3个事件,计算窗口内数据 */

keyedStream.countWindow(3);

以上满足3个才会计算一次,没有则不计算 。

flink怎么同时读多个topic flink获取两次窗口_数据

  • Sliding Count Window 滑动计数窗口 例子:一位用户每3次付款事件计算最近4次付款事件总金额。
/** 每3个事件,计算最近4个事件消息 */

keyedStream.countWindow(4,3);

flink怎么同时读多个topic flink获取两次窗口_ide_02

链接:countwindow的案例

Time Window

时间窗口,采用时间作为窗口处理依据。时间窗分为滚动和滑动两类,使用keyedStream.timeWindow实现时间窗定义。

  • Tumbling Time Window 滚动时间窗口:
/** 每1分钟,计算窗口数据 */

keyedStream.timeWindow( Time.minutes(1));

flink怎么同时读多个topic flink获取两次窗口_Time_03

  • Sliding Time Window 滑动时间窗口:
/** 每半分钟,计算最近1分钟窗口数据 */

keyedStream.timeWindow( Time.minutes(1), Time.seconds(30));

flink怎么同时读多个topic flink获取两次窗口_ide_04

参考案例:案例一

功能需求:对每天(00:00:00-23:59:59)、每小时(00:00-59:59)这个两个区间段内的数据进行统计。
发现滑动时间窗口不满足这个功能,查找资料后发现具有这个function:TumblingEventTimeWindows

对每小时的数据count:

import static flink.GetTime.dateToTimestamp;
import static stranger.PropertyLoader.getPropertiesConfig;

/**
 * @author 
 * @description 对每小时的数据进行统计
 * @date 2019/6/6
 */
public class EventTimeStreamWindowAll {
    public static void main(String[] args) {
        StreamExecutionEnvironment env = StreamExecutionEnvironment.getExecutionEnvironment();
        env.setStreamTimeCharacteristic(TimeCharacteristic.EventTime);

        final String configPath = "config.properties";
        final Properties pro = getPropertiesConfig(configPath);
        final String topic = "stranger";
        final String groupId = "mainStranger";
        String bootstrapServers = pro.getProperty("bootstrap.servers");
        Properties properties = new Properties();
        properties.setProperty("bootstrap.servers", bootstrapServers);//kafka的节点的IP或者hostName,多个使用逗号分隔
        properties.setProperty("group.id", groupId);//flink consumer flink的消费者的group.id
        FlinkKafkaConsumer011<String> kafkaSource = new FlinkKafkaConsumer011<>(topic, new SimpleStringSchema(), properties);
        kafkaSource.setStartFromLatest();
        SingleOutputStreamOperator<String> mainStream = env.addSource(kafkaSource).assignTimestampsAndWatermarks(new AssignerWithPeriodicWatermarks<String>() {
            @Nullable
            @Override
            public Watermark getCurrentWatermark() {
                return new Watermark(System.currentTimeMillis() - 5000);
            }

            @Override
            public long extractTimestamp(String s, long l) {
                String[] split = s.split("\\t");
                long timestamp = dateToTimestamp(split[0]);
                return timestamp;
            }
        });

        //2019-06-05 15:13:32,people6,进入,place3
        DataStream<Tuple5<String, String, String, String, Long>> mainCount = mainStream.map(new MapFunction<String, Tuple4<String, String, String, String>>() {
            @Override
            public Tuple4<String, String, String, String> map(String s) throws Exception {
                String[] split = s.split("\\t");
                return new Tuple4<>(split[0], split[1], split[2], split[3]);
            }
        }).keyBy(2)

                //以整点为窗口,每小时的窗口,offset 默认为0
                .windowAll(TumblingEventTimeWindows.of(Time.hours(1)))
                //以每天为窗口,进行统计
//                .windowAll(TumblingEventTimeWindows.of(Time.days(1),Time.hours(-8)))
                //每5秒触发一次
                .trigger(ContinuousEventTimeTrigger.of(Time.seconds(5)))
                //每多少条触发一次
//                .trigger(CountTrigger.of(1))
                .process(new ProcessAllWindowFunction<Tuple4<String, String, String, String>, Tuple5<String, String, String, String, Long>, TimeWindow>() {
                    @Override
                    public void process(Context context, Iterable<Tuple4<String, String, String, String>> iterables, Collector<Tuple5<String, String, String, String, Long>> collector) throws Exception {
                        Long sum = 0L;
                        String time = null;
                        String people = null;
                        String behavior = null;
                        String place = null;
                        for (Tuple4<String, String, String, String> iterable : iterables) {
                            sum += 1;
                            time = iterable.f0;
                            people = iterable.f1;
                            behavior = iterable.f2;
                            place = iterable.f3;
                        }
                        collector.collect(new Tuple5<>(time, people, behavior, place, sum));
                    }
                });

        mainCount.print();
        try {
            env.execute("test count");
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

Session Window

会话窗口,采用会话持续时长作为窗口处理依据。设置指定的会话持续时长时间,在这段时间中不再出现会话则认为超出会话时长。例子:每只股票超过2秒没有交易事件时计算窗口内交易总金额。下图中“消息A、消息B”代表两只不同的股票。

/** 会话持续2秒。当超过2秒不再出现会话认为会话结束 */

keyedStream.window( ProcessingTimeSessionWindows.withGap( Time.seconds(2)))

flink怎么同时读多个topic flink获取两次窗口_ide_05


窗口聚合 

聚合分为两类,一类是增量聚合,另一类是全量聚合。

增量聚合

窗口每进入一条数据,就计算一次:

flink怎么同时读多个topic flink获取两次窗口_ide_06

flink怎么同时读多个topic flink获取两次窗口_数据_07

常见的增量聚合函数有:

reduce(reduceFuction)

aggregate(aggregateFunction)

sum()

min()

max()

全量聚合

窗口触发的时候对窗口内的数据进行计算一次:

flink怎么同时读多个topic flink获取两次窗口_ide_08

flink怎么同时读多个topic flink获取两次窗口_ide_09

常见的全量聚合函数有:

apply(windowFunction)

process(processWindowFunction)