java - 在键上加入 2 个无界 Pcollections
问题描述
我正在尝试加入两个无界 PCollection,我基于一个键从 2 个不同的 kafka 主题中获得。
根据文档和其他博客,只有在我们进行窗口化时才能加入。Window 从特定窗口中的两个流中收集消息并将其加入。这不是我需要的。
预期的结果是在一个流中消息以非常低的频率出现,而从另一个流中我们以很高的频率获取消息。我希望如果密钥的值没有到达两个流上,我们不会在此之前进行连接,并且在它到达之后进行连接。是否可以使用当前的光束范例?
解决方案
简而言之,最好的解决方案是在 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
推荐阅读
- ios - 无法返回字符串数组中的项目
- r - 关于R的问题,如何取每个类别的平均值?
- javascript - 我用 let 声明了我的变量,但它仍然不在全局范围内
- python - Pyqtgraph水平条形图
- sql-server - 从不同的表中获取日期范围的计数天数
- php - 无法将数组值存储到 $sum
- server - 我的 Minecraft 服务器上的 Minecraft::tickEntity 有问题
- c++ - 从 std::vector 提取后如何覆盖派生函数
? - python - 提取熊猫数据框列中第一个引号之间的值
- r - 根据在另一个数据框中分配的四分位数计算数据框中某些数据的平均值