我正在尝试加入两个我在一个键的基础上从2个不同的kafka主题获得的无限制的PCollection。
根据文档和其他博客,仅当我们进行窗口化时,才可以加入。窗口从特定窗口中的两个流中收集消息并将其加入。这不是我所需要的。
预期结果是,一条消息中的消息以非常低的频率发送,而其他消息中的消息以高频率得到。我希望如果键的值没有同时到达两个流,则直到那时我们才进行连接,并且在到达之后再进行连接。 是否可以使用当前的光束范例?
答案 0 :(得分:2)
简而言之,最好的解决方案是在Beam中使用有状态的DoFn。您可以具有每个键状态(和每个窗口,在您的情况下为全局窗口)。您可以将一个流事件保存在状态中,并且一旦另一个流中的事件使用相同的键出现,则将其与状态中的事件一起加入。这是参考文献[1]。
但是,简短的答案没有利用Beam模型的真实功效。 Beam模型提供了在延迟,成本和准确性之间取得平衡的方法。它提供了简单的API以隐藏复杂的流处理。
为什么我这么说?让我们回到简短答案的解决方案:有状态的DoFn。在有状态DoFn方法中,您缺少解决以下问题的方法:
<1, a>
。稍后从左流还有另一个<1, c>
,您怎么知道只需要发射<1, <c, b>>
,假设这是增量模式即可输出结果。如果您开始缓冲那些已经加入的事件以获取增量,那么对于程序员来说确实变得太复杂了。 光束的窗口化,触发,对输出数据的优化,水印和延迟SLA控件旨在向您隐藏以下复杂对象:
尽管Beam模型设计合理。 Beam模型的实现缺少支持您描述的联接的关键功能:
总而言之,Beam模型旨在处理流处理中的复杂问题,非常适合您的需求。但是该实现不足以让您现在使用它来完成您的联接用例。
[1] https://beam.apache.org/blog/2017/02/13/stateful-processing.html
答案 1 :(得分:0)
当今的Beam模型并不能很好地支持这一点,但是有几种方法可以实现。这些示例假定每个键在每个流上仅出现一次,如果不是这种情况,则需要进行调整。
一种选择是使用Global Window和Stateful DoFn代替Join。全局窗口有效地关闭了窗口。有状态的DoFn可让您将有关要处理的密钥的数据存储在“状态单元”中,以备后用。收到记录时,将检查状态单元格中的值。如果找到一个,则执行联接,发出值并清除状态。如果没有任何内容,请存储当前值。
另一种选择是使用Session Windows和Join。会话窗口“ GapDuration”实际上是给定密钥的超时。只要有时间限制,您就可以在两个流中看到密钥。您还希望设置一个元素计数触发器“ AfterPane.elementCountAtLeast(2)”,这样您就不必在看到第二条数据后就等待整个超时。