Apache Beam最近通过StateSpec
和@StateId
注释引入了state cells,并在Apache Flink和Google Cloud Dataflow中提供了部分支持。
我找不到与GlobalWindow
一起使用时会发生什么的任何文档。特别是,是否有一种方法可以使用“状态垃圾收集”机制来摆脱根据某种配置暂时没有看到的键的状态,同时仍然保持键的单个所有时间状态经常够吗?
或者,在这种情况下使用的状态量是否会发散,无法回收与一段时间内未见过的键相对应的状态?
我也对Apache Flink或Google Cloud Dataflow是否支持潜在解决方案感兴趣。
Flink和直接跑步者似乎有一些“状态GC”的代码,但我不确定它的作用以及使用全局窗口时它是否相关。
答案 0 :(得分:2)
当窗口到期后某个时刻,Beam运行器会自动对状态进行垃圾回收 - 当输入水印超过窗口结束时允许的延迟时间,因此所有进一步输入都是可放弃的。确切的细节取决于跑步者。
正如您所确定的那样,全局窗口可能永不过期。然后将不会调用此自动状态集合。对于有界数据,包括排水情景,它实际上会过期,但对于永久无界数据源,它不会。
如果您在全局窗口中对此类数据进行有状态处理,则可以使用用户定义的计时器(通过@TimerId
,@OnTimer
和TimerSpec
使用) - 我还没有写博客关于这些)在你选择一些超时后清除状态。如果状态代表某种聚合,那么无论如何你都需要一个计时器来确保你的数据不会陷入状态。
以下是一个使用它们的简单示例:
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
方法中重新设置它。