水印的更新机制:
new = 当前到来数据的时间戳 - 乱序容忍时间
(例如:
.<WaterSensor>forBoundedOutOfOrderness(Duration.ofSeconds(1) 这里设置的是1S)
但是底层代码中 还会减1毫秒 准确的来说 应该是
new = 当前到来数据的时间戳 - 乱序容忍时间 - 1 毫秒
(new > 当前水印 ) ? new : 当前水印
如上举例 第一个数据到来的时间戳是 5000ms 所以他到来了之后更新水印为
5000 - 1000 - 1 = 3999ms
第二个数据到来的时间戳是 4000ms 这时2999 < 3999 所以水印不更新
第三个数据到来的时间戳是 6000ms 这时4999 > 3999 所以水印更新为 4999ms
注意:水印就好比现实生活的时钟 不管消费到的数据 事件时间是多少 都只会往前走不会倒退
(底层代码中
(new > 当前水印 ) ? new : 当前水印
这个表达式当前水印这里的初始值 是一个可视为 -∞ 的值 所以一旦来了第一条数据就会更新水印 )
水印代表的是 [ -∞ , 水印 ] 时间段的数据不再被接收
例如有两个窗口 [0,5000) ,[5000,1000)
第三个数据到来的时间戳是 6000ms 这时4999 > 3999 所以水印更新为 4999ms
当水印一旦>=4999ms 那么 [ -∞ , 4999]的数据不再被接收 [0,5000) 窗口触发计算
这里有一个允许延迟的设置
.allowedLateness(Time.seconds(1))
这里表示窗口触发计算了之后在 水印<= 窗口最大时间+延迟时间 内可以更新数据
如第三个数据到来的时间戳是 6000ms 这时4999 > 3999 所以水印更新为 4999ms
[0,5000) 窗口触发计算不再接收数据
但是 水印 < 4999 +1000ms 时 来了 [0,5000)窗口内的数据 会更新计算
设置乱序容忍时间 牺牲了实时性 保证了准确性
设置迟到时间 在没有牺牲实时性的情况下 还补充接收在迟到时间内晚来的数据 以此来更新之前发出的数据来保证准确性