Flink——WaterMark
WaterMark(水位线):
对由于网络、分布式等问题造成的乱序数据,事件不是严格地按照事件的 EventTime 顺序排列。一旦出现乱序,只根据 EventTime 决定 window 运行,不能明确保证数据是否到位。WaterMark 就是保证一个特定的事件后,必须出发 window 进行计算。
可以将 WaterMark 理解成一个延时触发机制,设置 WaterMark 的延时时长为 t,每次系统都会校验已经到达的数据中最大的 maxEventTime, 然后认定 EventTime 小于 maxEventTime - t 的所有数据到达,如果有窗口的停止时间等于 maxEventTime - t ,那么窗口触发执行。
WaterMark的引入:
// 引入时间 env.setStreamTimeCharacteristic(TimeCharacteristic.EventTime); //配置 WaterMark dataStream.assignTimestampsAndWatermarks(new BoundedOutOfOrdernessTimestampExtractor<SenorReading>(Time.seconds(1)) { @Override public long extractTimestamp(SenorReading sensor) { return sensor.getTimestamp(); } });
在1.12版本后,建议使用 WatermarkStrategy
dataStream.assignTimestampsAndWatermarks(WatermarkStrategy.<SensorReaing>forBoundedOutOfOrderness(Duration.ofSeconds(1)));
除了上述分配时间戳,Flink 还可以通过实现 TimestampAssigner 接口自定义地从事件中抽取时间戳。
TimestampAssigner 有两个子接口:
AssignerWithPeriodicWaterMarks:顾名思义,周期性地生成 WaterMark(系统会周期性地将watermark插入到流中),默认周期200毫秒。Flink 会定期调用 AssignerWithPeriodicWaterMarks 的 getCurrentTimestamp 方法,只有方法返回一个大于之前水位的时间戳,新的 watermark 就会插入流中。保证 水位线 单调递增。
当事先得知 数据流的时间戳是单调递增的,没有乱序。以事件的时间戳 生成 watermark。
// 设置 每隔5s 生成一个 WaterMark env.getConfig().setAutoWatermarkInterval(5000);
AssignerWithPunctuatedWaterMarks:间断式生成 WaterMark。不固定时间,根据需要对每条数据进行筛选和处理。
1 public static class MyPunctuatedAssigner implements AssignerWithPunctuatedWatermarks<SensorReaing> { 2 3 private static final Long bound = 60 * 1000L; 4 5 @org.jetbrains.annotations.Nullable 6 @Override 7 public Watermark checkAndGetNextWatermark(SensorReaing sensorReaing, long l) { 8 if (sensorReaing.getId().equals("sensor_1")){ 9 return new Watermark(l - bound); 10 } 11 return null; 12 } 13 14 @Override 15 public long extractTimestamp(SensorReaing sensorReaing, long l) { 16 return sensorReaing.getTimestamp() * 1000L; 17 } 18 }

浙公网安备 33010602011771号