在水印产生处设置一个乱序容忍度,可以推迟系统时间的推进,保证窗口计算被延迟执行,乱序的数据可以争取更多的时间去进入窗口
1、什么是乱序数据?
是指在流式数据计算时,发送的数据中偶尔出现数据的水印小于之前发送的数据水印
如何处理乱序数据?
1>设置乱序容忍度
//创建一个水印生成策略
//水印的场景 连续有序,偶尔乱序
WatermarkStrategy<WaterSensor> watermarkStrategy = WatermarkStrategy
//把系统的时钟调慢3S
.<WaterSensor>forBoundedOutOfOrderness(Duration.ofSeconds(3)).withTimestampAssigner(new SerializableTimestampAssigner<WaterSensor>() {
//从类型中抽取一个时间戳属性
@Override
public long extractTimestamp(WaterSensor waterSensor, long l) {
return waterSensor.getTs();
}
});
将系统时钟调慢3秒,调整后水印时间会比正常提取的ts时间慢3秒-1,这样就会拖延窗口计算时机,使得乱序数据能够进入到窗口
2>延迟窗口的关闭时间
在设置了乱序容忍度后依旧有乱序数据没有被计算到,就可以使用延迟窗口的关闭
//将窗口关闭的时间延迟5秒
.allowedLateness(Time.seconds(5))
窗口延迟的效果:
时钟到了窗口的end,会立即计算一次
设置延迟窗口的关闭事件后,计算后不会关闭,给后续的乱序数据提供了计算的机会,使其能够进入窗口
后续乱序数据进入窗口后每一条数据都会触发一次窗口计算
})
//从Event中提取数据作为水印
.assignTimestampsAndWatermarks(watermarkStrategy)
.windowAll(TumblingEventTimeWindows.of(Time.seconds(5)))
//允许迟到,窗口到end触发计算后不会立即关闭,为后续的乱序数据提供了进入窗口的机会
.allowedLateness(Time.seconds(5))
.process(new ProcessAllWindowFunction<WaterSensor, String, TimeWindow>() {
@Override
public void process(Context context, Iterable<WaterSensor> elements, Collector