Apache spark Spark作业脱离RAM(java.lang.OutOfMemoryError),即使存在';太多了。xmx太低了?
我的Spark作业中出现了java.lang.OutOfMemoryError,尽管只有20%的内存在使用 我尝试了几种配置:Apache spark Spark作业脱离RAM(java.lang.OutOfMemoryError),即使存在';太多了。xmx太低了?,apache-spark,google-cloud-platform,google-cloud-dataproc,Apache Spark,Google Cloud Platform,Google Cloud Dataproc,我的Spark作业中出现了java.lang.OutOfMemoryError,尽管只有20%的内存在使用 我尝试了几种配置: 1x n1-highmem-16+2x n1-highmem-8 3x n1-highmem-8 我的数据集由1.8M记录组成,这些记录从主节点上的本地json文件读取。json格式的整个数据集是7GB。我试图执行的工作包括一个简单的计算,然后是一个reduceByKey。没什么特别的。虽然需要一些磁盘缓存,但该作业在只有32GB ram(xmx28g)的单台家用计
- 1x n1-highmem-16+2x n1-highmem-8
- 3x n1-highmem-8
val rdd = sc.parallelize(Json.load()) // load everything
.map(fooTransform) // apply some trivial transformation
.flatMap(_.bar.toSeq) // flatten results
.map(c => (c, 1)) // count
.reduceByKey(_ + _)
.sortBy(_._2)
log.v(rdd.collect.map(toString).mkString("\n"))
问题的根源在于,您应该尝试将更多的I/O卸载到分布式任务,而不是在驱动程序和辅助任务之间来回传送。虽然有时不太清楚哪些调用是驱动程序本地调用,哪些调用描述了分布式操作,但经验法则包括避免
并行化
和收集
,除非您绝对需要将所有数据放在一个位置。在任何可能的最大机器类型下,您可以Json.load()
和parallelize
的数据量都将达到最大值,而像sc.textFile
这样的调用在理论上可以扩展到数百TB甚至PBs,没有问题
在您的情况下,短期的解决方法是尝试传递spark submit--conf spark.driver.memory=40g…
或该范围内的其他信息。Dataproc默认为驱动程序内存分配不到机器的四分之一,因为集群通常必须支持运行多个并发作业,并且还需要在主节点上为HDFS namenode和纱线资源管理器保留足够的内存
从长远来看,您可能希望尝试如何直接将JSON数据作为RDD加载,而不是将其加载到单个驱动程序中,然后使用parallelize
来分发它,因为这样可以通过让任务并行加载数据,大大加快输入读取时间(同时,消除警告阶段0包含一个非常大的任务
,这可能与将大数据从驱动程序传送到工作任务有关)
类似地,您可以执行类似于sc.saveAsTextFile
的操作,以分布式方式进行保存,而不必在单个位置进行瓶颈限制,而不是collect
然后在驱动程序上完成操作
将输入读取为
sc.textFile
将采用行分隔的JSON,您可以在一些map
任务中进行解析,也可以尝试使用。出于调试目的,通常不使用collect()
来调用take(10)
查看一些记录而不将其全部发送给驱动程序。问题的根源在于,您应该尝试将更多的I/O卸载到分布式任务,而不是在驱动程序和工作任务之间来回发送。虽然有时可能不清楚哪些调用是驱动程序本地调用,哪些调用是非本地调用描述一个分布式操作,经验法则包括避免parallelize
和collect
,除非您绝对需要将所有数据放在一个位置。您可以Json.load()的数据量
和并行化
将在任何可能的最大机器类型下最大化,而使用诸如sc.textFile
之类的调用理论上可以扩展到数百TB甚至PBs,没有问题
在您的情况下,短期修复方法是尝试传递spark submit--conf spark.driver.memory=40g…
或该范围内的内容。Dataproc默认情况下,将不到四分之一的计算机分配给驱动程序内存,因为集群通常必须支持运行多个并发作业,并且还需要在m上保留足够的内存用于HDFS名称节点和纱线资源管理器的aster节点
从长远来看,您可能希望尝试如何直接将JSON数据作为RDD加载,而不是将其加载到单个驱动程序中,然后使用parallelize
来分发它,因为这样可以通过让任务并行加载数据,大大加快输入读取时间(同时,消除警告阶段0包含一个非常大的任务
,这可能与将大数据从驱动程序传送到工作任务有关)
类似地,您可以执行类似于sc.saveAsTextFile
的操作,以分布式方式进行保存,而不必在单个位置进行瓶颈限制,而不是collect
然后在驱动程序上完成操作
将输入读取为
sc.textFile
将采用行分隔的JSON,您可以在一些map
任务中进行解析,也可以尝试使用。出于调试目的,通常不使用collect()
来调用take(10)
在不将所有记录发送给驱动程序的情况下查看一些记录。您能展示一下如何在节点之间分发RDD-s吗?这是我第一次使用多个节点。我添加了一段相关的Spark代码。我需要手动对其进行分区吗?如果我误解了您的问题,很抱歉。我仍然很抱歉挣钱。你能展示一下你是如何在节点之间分配RDD-s的吗?这是我第一次处理的不仅仅是一个节点。我添加了一段相关的Spark代码。我需要手动划分吗?如果我误解了你的问题,我很抱歉。我还在学习。哦,天哪,你说得很有道理。结果我真的不明白我认为两者都是以一种类似于sc.textFile的方式工作的——但是是的