使用源自Cloud PubSub订阅的Google Dataflow中的流媒体无界PCollection。我们使用它作为一个firehose来简单地连续向BigTable传递事件。交付的一切都很好。
我们的问题是我们有下游批量作业,一旦交付,他们希望从BigTable中读取一天的数据。我想利用窗口和触发来实现副作用,当水印超过日期阈值时,会将标记行写入bigtable,表明数据流有理由相信大多数事件已经发送(我们不要&# 39;需要强有力的完整性保证,只需要合理的保证)并且下游处理可以开始。
我们尝试过将原始事件写为管道中的一个接收器,然后使用the timing information in the pane窗口进入另一个接收器以确定水印是否已经前进。这种方法的问题在于它再次对原始事件本身进行操作,这是不希望的,因为它会重复写入事件行。我们可以阻止这种写入,但是管道中的并行路径仍将在窗口化的事件流上运行。
是否有一种有效的方法可以对水印附加回调,以便我们可以在水印前进时执行单个操作?
答案 0 :(得分:1)
在事件时间设置计时器并接收回调的一般能力绝对是一个重要的功能请求,归档为BEAM-27,正在积极开发中。
但实际上,您使用FixedWindows.of(Duration.standardDays(1))
窗口的方法似乎只使用Dataflow Java SDK 1.x的功能来实现您的目标。您可以维护" firehose"而不是分叉您的管道。添加触发器AfterPane.elementCountAtLeast(1)
的行为。它会产生GroupByKey
的成本,但不会重复任何内容。
完整的管道可能如下所示:
pipeline
// Read your data from Cloud Pubsub and parse to MyValue
.apply(PubsubIO.Read.topic(...).withCoder(MyValueCoder.of())
// You'll need some keys
.apply(WithKeys.<MyKey, MyValue>of(...))
// Window into daily windows, but still output as fast as possible
.apply(Window.into(FixedWindows.of(Duration.standardDays(1)))
.triggering(AfterPane.elementCountAtLeast(1)))
// GroupByKey adds the necessary EARLY / ON_TIME / LATE labeling
.apply(GroupByKey.<MyKey, MyValue>create())
// Convert KV<MyKey, Iterable<MyValue>>
// to KV<ByteString, Iterable<Mutation>>
// where the iterable of mutations has the "end of day" marker if
// it was ON_TIME
.apply(MapElements.via(new MessageToMutationWithEndOfWindow())
// Write it!
.apply(BigTableIO.Write.to(...);
如果我错过了一些用例的详细信息,请对我的回答发表评论。