我想加载流数据,然后添加一个键,然后按键对它们进行计数。
当我尝试使用流传输方法(无界数据)加载和按密钥对大型数据进行分组时,Apache Beam Dataflow样条线会出现内存错误 。因为似乎数据是按组累积的,并且不会在触发每个窗口时更早触发数据。
如果我减小元素大小(元素数不会改变),它将起作用!因为实际上分组操作会等待所有数据被分组,然后触发所有新的窗口数据。
我对两者都进行了测试
beam版本2.11.0和scio版本0.7.4
beam 2.6.0版和scio 0.6.1版
如您所见,数据是按组累积的,不会被发出。
val windowedData = data.applyKvTransform(
Window.into[myt](
Sessions.withGapDuration(Duration.millis(1)))
.triggering(
Repeatedly.forever(AfterFirst.of(
AfterPane.elementCountAtLeast(10),
AfterProcessingTime.pastFirstElementInPane().plusDelayOf(Duration.millis(1)))
).orFinally(AfterWatermark.pastEndOfWindow())
).withAllowedLateness(Duration.standardSeconds(100))
.discardingFiredPanes()
)
org.apache.beam.runners.dataflow.worker.StreamingDataflowWorker$KeyCommitTooLargeException: Commit request for stage S2 and key 2 is larger than 2GB and cannot be processed. This may be caused by grouping a very large amount of data in a single window without using Combine, or by producing a large amount of data from a single input element.
org.apache.beam.runners.dataflow.worker.StreamingDataflowWorker$KeyCommitTooLargeException.causedBy(StreamingDataflowWorker.java:230)
org.apache.beam.runners.dataflow.worker.StreamingDataflowWorker.process(StreamingDataflowWorker.java:1287)
org.apache.beam.runners.dataflow.worker.StreamingDataflowWorker.access$1000(StreamingDataflowWorker.java:146)
org.apache.beam.runners.dataflow.worker.StreamingDataflowWorker$6.run(StreamingDataflowWorker.java:1008)
java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)
java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
java.lang.Thread.run(Thread.java:745)
是否有解决方法,可以通过强制group-by发出每个窗口的早期结果来解决内存问题。
答案 0 :(得分:1)
KeyCommitTooLargeException不是内存问题,而是protobuf序列化问题。 Protobuf对一个对象(google protobuf maximum size)的限制为2GB。数据流发现,管道中单个键的值大于2GB,因此无法对数据进行混洗。错误消息指示“这可能是由于在不使用合并的情况下将单个窗口中的大量数据分组或从单个输入元素产生大量数据引起的。”根据您的管道设置(即分配的随机密钥),后者更有可能。
管道可能已从GCS读取了一个大文件(> 2GB),并将其分配给了随机密钥。 GroupByKey要求进行密钥混洗操作,并且由于protobuf限制而导致Dataflow失败,因此卡在该密钥上并保持水印。
如果单个键的值较大,则可能需要减小值的大小,例如,压缩字符串,或将字符串拆分为多个键,或者首先生成较小的GCS文件。
如果较大的值来自多个键的分组,则可能需要增加键空间,以便每个按键操作的组最终将较少的键组合在一起。