在Apache Beam中使用固定Windows。水印由事件时间设置。
某些数据可能会乱序到达并导致窗口关闭。
如何在Java中定义一个触发器,使其在看到最后一个数据2分钟后发生?
答案 0 :(得分:0)
目前尚不清楚您期望什么行为。一个问题是,如果数据在两分钟内到达,您期望发生什么?是否要重新启动两分钟间隔,不重新启动,不重新发送数据?
就像您要描述的触发器一样,它们是这样的:
如果在步骤2中是事件时间,也就是说,如果要到达window + 2min
内的延迟元素到达,您想重新发出窗口,则可以使用withAllowedLateness()
。尽管这听起来与您想要的有所不同,但是因为它可以在每次匹配的后期元素到达时不断重发窗口内容。
对于第2步中的处理时间,通常使用Beam中可用的基本触发器是不可能的。如果您manually manage state and timers in your own ParDo
,例如您可以监视传入的元素,在状态中对其进行跟踪,然后在计时器上发出所需的内容。对于您的特定用例,这可能变得非常复杂,并且可能仍然不够灵活。
主要问题之一是,通常没有一种好的方法可以在Beam中定义处理时间触发器。定义以这种方式使用计时器的一般机制将很复杂。例如,当您想表达"wait for 2 minutes"
时,框架需要了解这两个分钟是什么,何时启动计时器,因此还需要一种机制来表达它。而且对于构图,延续和其他并发症,这似乎并不容易推断。因此它不在这种通用形式的框架中。
为了仅实现"wait for 2 minutes after the last element was seen in the window"
,框架必须对其进行监视并设置计时器。从技术上讲,可以做这样的事情,但似乎还没有人做过。
Beam中似乎有only one个有意义的处理时间触发器,但它不够通用,不能满足您的要求。您可以查看AfterFirst
或AfterAll
之类的复合触发器,但是如果没有更好的常规处理时间触发器,它们可能对您没有帮助。
答案 1 :(得分:0)
我决定不使用Beam并在Kafka Streams中实施该解决方案。
我基本上按分组,然后使用固定的窗口并将结果汇总。 窗口上的“宽限期”允许数据延迟到达。
KGroupedStream<Long, OxyStreamItem> grouped = input.groupByKey();
TimeWindowedKStream<Long, OxyStreamItem> windowed =
grouped.windowedBy(
TimeWindows.of(WIN_SIZE)
.advanceBy(WIN_SIZE)
.grace(Duration.ofSeconds(5L)));
return windowed
.aggregate(
makeInitializer(),
makeAggregator(),
Materialized
.<Long, Aggregate, WindowStore<Bytes, byte[]>>as("tmp")
.withValueSerde(new AggregateSerde()))
.suppress(
Suppressed.untilWindowCloses(Suppressed.BufferConfig.unbounded()))
.toStream()
.map(calculateAvg());