首页 > 解决方案 > 在键上加入 2 个无界 Pcollections

问题描述

我正在尝试加入两个无界 PCollection,我基于一个键从 2 个不同的 kafka 主题中获得。

根据文档和其他博客,只有在我们进行窗口化时才能加入。Window 从特定窗口中的两个流中收集消息并将其加入。这不是我需要的。

预期的结果是在一个流中消息以非常低的频率出现,而从另一个流中我们以很高的频率获取消息。我希望如果密钥的值没有到达两个流上,我们不会在此之前进行连接,并且在它到达之后进行连接。是否可以使用当前的光束范例?

标签: javastreamgoogle-cloud-dataflowapache-beamapache-beam-io

解决方案


简而言之,最好的解决方案是在 Beam 中使用 stateful DoFn。您可以拥有每个键状态(以及每个窗口,在您的情况下是全局窗口)。您可以将一个流事件保存在状态中,并且一旦来自另一个流的事件以相同的键出现,将其与状态中的事件连接起来。这是一个参考[​​1]。

然而,简短的回答并没有利用 Beam 模型的真正力量。Beam 模型提供了在延迟、成本和准确性之间进行平衡的方法。它提供了简单的 API 来隐藏复杂的流处理。

为什么我这么说?让我们回到简短答案的解决方案:有状态的 DoFn。在有状态的 DoFn 方法中,您缺乏解决以下问题的方法:

  • 如果您为一个键缓冲了 1M 事件,但仍然没有从另一个流中出现事件怎么办?你需要清空状态吗?如果事件在您清空状态后立即出现怎么办?
  • 如果最终有一个事件似乎完成了 JOIN,缓冲 1M 事件的成本对于 JOIN 来自另一个流的单个事件是否可接受?
  • 如何处理两个流的迟到?假设您<1, a>已从右侧流的 <1, b> 上的左侧流加入。后来还有一个<1, c>来自左流的,你怎么知道你只需要发出<1, <c, b>>,假设这是输出结果的增量模式。如果你开始缓冲那些已经加入的事件以获得增量,那对于程序员来说真的变得太复杂了。

Beam 的窗口化、触发、输出数据优化、水印和延迟 SLA 控制旨在隐藏这些复杂性:

  • 水印:告诉窗口何时完成,以便事件不会很快到来(并且进一步的事件被视为迟到的数据)
  • 延迟 SLA 控制:控制缓存数据以供加入的时间。
  • 输出数据的细化:如果允许新事件到达,则正确更新输出。

虽然 Beam 模型设计得很好。Beam 模型的实现缺少支持您描述的连接的关键功能:

  • 窗口不够灵活,无法支持流具有不同频率的情况(因此固定窗口和滑动窗口不适合)。而且您也不知道流的到达率(因此会话窗口并不真正适合,因为您必须在会话窗口之间留出间隙)。
  • 缺少撤回,因此一旦迟到的事件到达,您就无法优化输出。

总而言之,Beam 模型旨在处理复杂的流处理,完全符合您的需求。但是实现还不足以让您现在使用它来完成您的加入用例。

[1] https://beam.apache.org/blog/2017/02/13/stateful-processing.html


推荐阅读