使用GlobalWindow在Beam中进行状态垃圾收集

时间:2017-03-13 20:41:07

标签: google-cloud-dataflow apache-flink apache-beam

Apache Beam最近通过StateSpec@StateId注释引入了state cells,并在Apache Flink和Google Cloud Dataflow中提供了部分支持。

我找不到与GlobalWindow一起使用时会发生什么的任何文档。特别是,是否有一种方法可以使用“状态垃圾收集”机制来摆脱根据某种配置暂时没有看到的键的状态,同时仍然保持键的单个所有时间状态经常够吗?

或者,在这种情况下使用的状态量是否会发散,无法回收与一段时间内未见过的键相对应的状态?

我也对Apache Flink或Google Cloud Dataflow是否支持潜在解决方案感兴趣。

Flink和直接跑步者似乎有一些“状态GC”的代码,但我不确定它的作用以及使用全局窗口时它是否相关。

2 个答案:

答案 0 :(得分:2)

当窗口到期后某个时刻,Beam运行器会自动对状态进行垃圾回收 - 当输入水印超过窗口结束时允许的延迟时间,因此所有进一步输入都是可放弃的。确切的细节取决于跑步者。

正如您所确定的那样,全局窗口可能永不过期。然后将不会调用此自动状态集合。对于有界数据,包括排水情景,它实际上会过期,但对于永久无界数据源,它不会。

如果您在全局窗口中对此类数据进行有状态处理,则可以使用用户定义的计时器(通过@TimerId@OnTimerTimerSpec使用) - 我还没有写博客关于这些)在你选择一些超时后清除状态。如果状态代表某种聚合,那么无论如何你都需要一个计时器来确保你的数据不会陷入状态。

以下是一个使用它们的简单示例:

new DoFn<Foo, Baz>() {

  private static final String MY_TIMER = "my-timer";
  private static final String MY_STATE = "my-state";

  @StateId(MY_STATE)
  private final StateSpec<ValueState<Bizzle>> =
      StateSpec.value(Bizzle.coder());

  @TimerId(MY_TIMER)
  private final TimerSpec myTimer =
      TimerSpecs.timer(TimeDomain.EVENT_TIME);

  @ProcessElement
  public void process(
      ProcessContext c,
      @StateId(MY_STATE) ValueState<Bizzle> bizzleState,
      @TimerId(MY_TIMER) Timer myTimer) {
    bizzleState.write(...);
    myTimer.setForNowPlus(...);
  }

  @OnTimer(MY_TIMER)
  public void onMyTimer(
      OnTimerContext context,
      @StateId(MY_STATE) ValueState<Bizzle> bizzleState) {
    context.output(... bizzleState.read() ...);
    bizzleState.clear();
  }
}

答案 1 :(得分:1)

如果您使用GlobalWindows,则没有自动垃圾收集状态。只有当你使用一些非全局窗口时,才会在水印通过窗口结束加上允许的延迟后进行垃圾收集。

如果您必须使用GlobalWindows,则可以执行的操作是手动保持last update timestamp状态。然后,您将定期设置一个计时器,您可以根据当前时间检查此时间戳,并在必要时删除状态。您可以在第一次遇到密钥时设置此计时器(您可以从缺少时间戳状态看到),然后在@OnTimer方法中重新设置它。