Apache Beam 中的批处理开销很大

Batch Processing in Apache Beam with large overhead

我目前正在使用 Python API 开发更大的 Apache Beam 管道,它从 BigQuery 读取数据,最后将其写回另一个 BigQuery 任务。

其中一个转换需要使用二进制程序来转换数据,为此它需要加载一个包含二进制查找数据的 23GB 文件。因此,启动和 运行 程序需要大量的开销(每次 load/run 大约需要 2 分钟)和 RAM,并且只为一条记录启动它是没有意义的。加上23GB的文件每次都需要从云存储复制到本地。

二进制文件的工作流程为:

  1. 从云存储中复制 23GB 文件(如果还没有)

  2. 将记录保存到文件

  3. 运行 带有 call()

  4. 的二进制文件
  5. 读取二进制文件的输出并return它

程序一次可以处理的记录数量基本上是无限的,所以如果能得到一个稍微分布式的 Beam Transform 会很好,我可以在其中指定一次要处理的记录数量(比如 100 '000 一次),但仍将其分发,因此它可以 运行 一次在多个节点上处理 100'000 条记录。

我没有看到 Beam 支持这种行为,它可能会把一些东西组合在一起作为 KeyedCombineFn 操作,它根据一些拆分 criterion/key 收集记录,然后 运行s 中的二进制文件merge_accumulators 跨过累积的记录。但这对我来说似乎很老套。

或者是否可以GroupByKey和批处理组?这是否保证每个组都被一次处理,或者组可以在幕后由 Beam 拆分?

我还看到 Java API 中有一个 GroupIntoBatches,这听起来像我需要的,但据我所知 Python SDK 中没有可以说。

我的两个问题是,在 Apache Beam 中实现此用例的最佳方式(性能方面)是什么?如果没有好的解决方案,是否还有其他一些 Google 云服务可能更适合可以像 Beam --> Other Service --> Beam ?

这样使用

无法在后台拆分组,因此使用 GroupByKey 应该可行。事实上,这是一项要求,因为每个单独的元素都必须在一台机器上处理,并且在 GroupByKey 之后,具有给定键的所有值都是同一元素的一部分。

您可能想要分配随机密钥。请记住,如果给定键有太多值,可能也很难将所有这些值传递给您的程序——因此您可能还想限制一次传递给程序的值的数量and/or 调整您分配按键的方式。

分配随机键的一个技巧是在起始包中生成随机数(比如 1 到 1000),然后在处理元素中递增它并将 1001 包装到 1000。这避免了为每个元素生成随机数,并且仍然确保密钥的良好分配。

您可以为这两种逻辑创建一个 PTransform(将 PCollection<T> 分成 PCollection<List<T>> 块进行处理),这可能会在类似情况下重复使用。