Apache Beam中的批处理具有较大的开销

时间:2017-07-06 07:31:32

标签: python google-cloud-platform google-cloud-dataflow apache-beam

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

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

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

  1. 从云存储中复制23GB文件(如果尚未存在)

  2. 将记录保存到文件

  3. 使用call()

  4. 运行二进制文件
  5. 读取二进制文件的输出并将其返回

  6. 程序一次可以处理的记录数量基本上是无限的,所以最好能得到一个分布式的Beam Transform,我可以指定一次要处理的记录数(比如100'000)在一次),但仍然分布,所以它可以在多个节点上一次运行100'000条记录。

    我没有看到Beam支持这种行为,有可能将一些东西一起作为KeyedCombineFn操作,根据某些拆分条件/密钥收集记录,然后在merge_accumulators步骤中运行累积记录中的二进制文件。但这对我来说似乎非常苛刻。

    或者可以将GroupByKey和进程组作为批次进行处理吗?这是否保证每个组一次处理,或者可以通过Beam在幕后拆分组?

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

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

1 个答案:

答案 0 :(得分:1)

无法在幕后拆分组,因此使用GroupByKey应该可以正常工作。实际上,这是一个要求,因为每个单独的元素必须在一台机器上处理,而在GroupByKey之后,具有给定键的所有值都是同一元素的一部分。

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

分配随机密钥的一个技巧是在启动包中生成随机数(比如1到1000),然后在进程元素中只增加它并将1001包装为1000.这可以避免为每个元素生成一个随机数,并且仍然确保密钥的良好分配。

你可以为这个逻辑创建一个PTransform(将PCollection<T>划分为PCollection<List<T>>个块进行处理),这在类似的情况下可能是可重用的。