将固定窗口延迟触发几分钟

时间:2019-07-04 20:46:02

标签: apache-beam

在Apache Beam中使用固定Windows。水印由事件时间设置。

某些数据可能会乱序到达并导致窗口关闭。

如何在Java中定义一个触发器,使其在看到最后一个数据2分钟后发生?

2 个答案:

答案 0 :(得分:0)

目前尚不清楚您期望什么行为。一个问题是,如果数据在两分钟内到达,您期望发生什么?是否要重新启动两分钟间隔,不重新启动,不重新发送数据?

就像您要描述的触发器一样,它们是这样的:

  • 在事件发生之前,等待水印通过窗口的结尾;
  • 等待另外2分钟的处理时间;
  • 发送数据;

如果在步骤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个有意义的处理时间触发器,但它不够通用,不能满足您的要求。您可以查看AfterFirstAfterAll之类的复合触发器,但是如果没有更好的常规处理时间触发器,它们可能对您没有帮助。

答案 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());