我们使用Combine.PerKey和自定义KeyedCombineFn对几个PCollections执行连接。在AfterProcessingTime.pastFirstElementInPane上使用Repeatedly.forever触发器将PCollections分配给GlobalWindow。
PCollections包含大约1M个键,但对于给定键,只有几百个元素。 KeyedCombineFn在其累加器中保留大约几KB(有时高达5 MB)的数据。
现在我们已经增加了我们在管道中处理的数据量,我们看到java.lang.OutOfMemoryError:Java堆空间错误。该管道在Google Cloud Dataflow上的n1-highmem-4计算机上运行。
我们的假设是Dataflow工作人员独立地管理每个密钥的状态,并具有启发式功能,可根据可用的RAM数量将其写入/加载到磁盘。因此,目标是让个人状态适合一个工人的记忆。
这个假设是否正确?如果是这样,为什么我们会看到OOM错误?如果没有,您是否介意详细说明Dataflow工作人员如何在内存中管理状态?
答案 0 :(得分:1)
数据流工作人员的行为大致与您假设的一样,但是涉及到一些估算,并且您的数据可能会破坏这一点。在累加器的序列化大小和对象的内存大小方面是否存在非常大的差异?
最容易解决的问题是在较少的大型机器上运行,例如n1-highmem-8