flink水位线

文章目录

  • 水位线概念
  • 水位线API
    • flink内置水位线生成器
    • 自定义水位线策略
    • 延迟时间

水位线概念

flink中水位线是个时间的概念,每条消息由发出该消息的机器打上了一个时间戳,flink收到这些消息会拿到其中的时间戳,并以收到的所有消息中最大的时间戳作为flink自己的当前时间。

水位线API

通过DataStream的assignTimestampsAndWatermarks(WatermarkStrategy watermarkStrategy) 方法可以设置水位线策略,水位线策略主要需要重写两个方法

用于设置水位线的生成策略(定时或者断点。定时指flink每隔相同的时间产生一个水位线;断点指flink每收到一条消息就产生一个水位线)
WatermarkGenerator<T> createWatermarkGenerator(WatermarkGeneratorSupplier.Context context);
用于设置如何提取消息中的时间戳,每个实体类中的时间戳属性命名不同,通常是设置取实体类的那个属性作为时间戳
default TimestampAssigner<T> createTimestampAssigner(TimestampAssignerSupplier.Context context)

flink内置水位线生成器

(1)针对有序流:WatermarkStrategy.forMonotonousTimestamps()
此方法只设置了水位线的生成策略,没有设置如何提取每条消息中的时间戳,所以还需要设置从消息中提取时间戳的策略。举例如下:

StreamExecutionEnvironment env = StreamExecutionEnvironment.getExecutionEnvironment();
        env.fromElements(new Event("Jack", 1000L, "./home"),
                new Event("Tom", 2000L, "./cart"),
                new Event("Jerry", 1300L, "./prod?id=10"))
                .assignTimestampsAndWatermarks(WatermarkStrategy.<Event>forMonotonousTimestamps()
                        .withTimestampAssigner(new SerializableTimestampAssigner<Event>() {
                            @Override
                            public long extractTimestamp(Event element, long recordTimestamp) {
                                return element.getTimestamp();
                            }
                        })
                );

(2)针对无序流
调用 WatermarkStrategy. forBoundedOutOfOrderness() 方法就可以实现。这个方法需要传入一个 maxOutOfOrderness 参数,表示“最大乱序程度”,它表示数据流中乱序数据时间戳的最大差值;如果我们能确定乱序程度,那么设置对应时间长度的延迟,就可以等到所有的乱序数据了,与有序流一样也还需要设置消息时间戳提取策略,举例如下(延迟2s):

StreamExecutionEnvironment env = StreamExecutionEnvironment.getExecutionEnvironment();
        env.fromElements(new Event("Jack", 1000L, "./home"),
                new Event("Tom", 2000L, "./cart"),
                new Event("Jerry", 1300L, "./prod?id=10"))
                .assignTimestampsAndWatermarks(WatermarkStrategy.<Event>forBoundedOutOfOrderness(Duration.ofSeconds(2))
                        .withTimestampAssigner(new SerializableTimestampAssigner<Event>() {
                            @Override
                            public long extractTimestamp(Event element, long recordTimestamp) {
                                return element.getTimestamp();
                            }
                        })
                );

自定义水位线策略

自定义水位线策略实际就是重写 WatermarkStrategycreateWatermarkGeneratorcreateTimestampAssigner 两个方法,用来设置水位线的生成策略以及时间戳的提取方式,举例如下(水位线):

StreamExecutionEnvironment env = StreamExecutionEnvironment.getExecutionEnvironment();
        env.fromElements(new Event("Jack", 1000L, "./home"),
                new Event("Tom", 2000L, "./cart"),
                new Event("Jerry", 1300L, "./prod?id=10"))
                .assignTimestampsAndWatermarks(new WatermarkStrategy<Event>() {

                    @Override
                    public TimestampAssigner<Event> createTimestampAssigner(TimestampAssignerSupplier.Context context) {
                        return new TimestampAssigner<Event>() {
                            @Override
                            public long extractTimestamp(Event element, long recordTimestamp) {
                                return element.getTimestamp();
                            }
                        };
                    }

                    @Override
                    public WatermarkGenerator<Event> createWatermarkGenerator(WatermarkGeneratorSupplier.Context context) {
                        return new WatermarkGenerator<Event>() {

                            private Long maxTimestamp;  //观察到的最大时间
                            private Long delayTime = 5000L; //延迟时间

                            @Override
                            public void onEvent(Event event, long eventTimestamp, WatermarkOutput output) {
                                //每来一条数据就更新一下flink服务器系统最大时间
                                maxTimestamp = Math.max(event.getTimestamp(), maxTimestamp);
                            }

                            @Override
                            public void onPeriodicEmit(WatermarkOutput output) {
                                //产生水位线,默认200ms一次
                                output.emitWatermark(new Watermark(maxTimestamp - delayTime - 1L));
                            }
                        };
                    }
                });

延迟时间

这里都有一个延迟时间的概念,即flink收到的消息中的最大时间不认为是当前的时间,举个例子假如flink收到消息中的最大时间是12s,延迟时间是2s,则flink认为当前时间是10s,如果此时发送水位线也是发送的10s的水位线。这样做的原因是为了等待那些先产生但是迟到的数据。

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