Flink水位线

目录

水位线生成策略

1、有序流中内置水位线设置

2、乱序流水位线设置

水位线的传递

迟到数据的处理

1、设置乱序容忍度

2、设置窗口延迟关闭

3、使用侧输出流接受迟到的数据

基于时间的合流(join)

1、window join

2、interval join


水位线生成策略

        在Flink的DataStream API中,有一个单独用于生成水位线的方法,assignTimestampsAndWatermarks,它用于为流数据分配时间戳,并生成水位线来指示事件时间。

        WatermarkStrategy是一个接口,该接口中包含了一个“时间戳分配器”TimestampAssigner和一个“水位线生成器”WatermarkGenerator。该接口包括一个时间戳分配器和一个水位线生成器。

Flink水位线_第1张图片

        下面演示如何使用flink内置水位线

1、有序流中内置水位线设置

        对于有序流,时间戳单调递增,不存在乱序、迟到的情况,直接调用WatermarkStrategy.forMonotonousTimestamps()方法即可实现

public static void main(String[] args) throws Exception {
        StreamExecutionEnvironment env = StreamExecutionEnvironment.getExecutionEnvironment();
        env.setParallelism(1);

        SingleOutputStreamOperator source = env
                .socketTextStream("node1", 7777)
                .map(new WaterSensorMapFunction());

        // TODO 1.定义Watermark策略
        WatermarkStrategy watermarkStrategy = WatermarkStrategy
                // 1.1 指定watermark生成:升序的watermark,没有等待时间
                .forMonotonousTimestamps()
                // 1.2 指定 时间戳分配器,从数据中提取
                .withTimestampAssigner(new SerializableTimestampAssigner(){
                    @Override
                    public long extractTimestamp(WaterSensor waterSensor, long l) {
                        // 返回的时间戳,要 毫秒
                        System.out.println("数据=" + waterSensor + ",recordTs=" + l);
                        // 返回的时间戳单位为毫秒
                        return waterSensor.getTs() * 1000L;
                    }
                });

        // TODO 2. 指定 watermark策略
        SingleOutputStreamOperator watermark = source.assignTimestampsAndWatermarks(watermarkStrategy);

        KeyedStream keyBy = watermark.keyBy(
                new KeySelector() {
                    @Override
                    public String getKey(WaterSensor waterSensor) throws Exception {
                        return waterSensor.getId();
                    }
                }
        );

        // TODO 3.使用 事件时间语义 的窗口
        WindowedStream sensorWS = keyBy.window(TumblingEventTimeWindows.of(Time.seconds(10)));

        SingleOutputStreamOperator process = sensorWS.process(
                // IN,KEY,OUT,Window
                new ProcessWindowFunction() {
                    @Override
                    public void process(String s, Context context, Iterable iterable, Collector collector) throws Exception {
                        // 拿到窗口的开始时间、结束时间
                        long startTS = context.window().getStart();
                        long endTS = context.window().getEnd();
                        String start_time = DateFormatUtils.format(startTS, "yyyy-MM-dd HH:mm:ss.SSS");
                        String end_time = DateFormatUtils.format(endTS, "yyyy-MM-dd HH:mm:ss.SSS");
                        // 去除窗口的size
                        long count = iterable.spliterator().estimateSize();
                        collector.collect("key=" + s + "的窗口[" + start_time + "->" +
                                end_time + "),长度为" + count + "条数据---->" + iterable.toString());
                    }

                }
        );
        process.print();


        env.execute();
    }

          有序流中,数据严格单增,在测试的时候输入几条乱序的数据,可以发现对应[0,10)秒的窗口在水位线为10s的数据到达后已经关闭,后面的乱序数据不会被放入任意一个窗口,因此乱序数据有特定的api,使用时按需选择。

Flink水位线_第2张图片

Flink水位线_第3张图片

2、乱序流水位线设置

        乱序流中需要等待迟到的数据,因此需要设置一个迟到时间,例如size为10s的窗口,延迟时间设置为3s,那么直到事件时间为13s的数据到达,才会促发[0,10)的窗口执行,输出。调用WatermarkStrategy. forBoundedOutOfOrderness()方法就可以实现。这个方法需要传入一个maxOutOfOrderness参数,表示“最大乱序程度”,它表示数据流中乱序数据时间戳的最大差值,也就是等待的时间。

public static void main(String[] args) throws Exception {
        StreamExecutionEnvironment env = StreamExecutionEnvironment.getExecutionEnvironment();
        env.setParallelism(1);

        SingleOutputStreamOperator source = env
                .socketTextStream("node1", 7777)
                .map(new WaterSensorMapFunction());

        // TODO 1.定义Watermark策略
        WatermarkStrategy watermarkStrategy = WatermarkStrategy
                // 1.1 指定watermark生成:乱序,等待3s
                .forBoundedOutOfOrderness(Duration.ofSeconds(3))
                // 1.2 指定 时间戳分配器,从数据中提取
                .withTimestampAssigner(new SerializableTimestampAssigner(){
                    @Override
                    public long extractTimestamp(WaterSensor waterSensor, long l) {
                        // 返回的时间戳,要 毫秒
                        System.out.println("数据=" + waterSensor + ",recordTs=" + l);
                        // 返回的时间戳单位为毫秒
                        return waterSensor.getTs() * 1000L;
                    }
                });

        // TODO 2. 指定 watermark策略
        SingleOutputStreamOperator watermark = source.assignTimestampsAndWatermarks(watermarkStrategy);

        KeyedStream keyBy = watermark.keyBy(
                new KeySelector() {
                    @Override
                    public String getKey(WaterSensor waterSensor) throws Exception {
                        return waterSensor.getId();
                    }
                }
        );

        // TODO 3.使用 事件时间语义 的窗口
        WindowedStream sensorWS = keyBy.window(TumblingEventTimeWindows.of(Time.seconds(10)));

        SingleOutputStreamOperator process = sensorWS.process(
                // IN,KEY,OUT,Window
                new ProcessWin

你可能感兴趣的:(flink,大数据)