Apache spark 处理大数据集时FetchFailedException或MetadataFetchFailedException
当我用1GB的数据集运行解析代码时,它就完成了,没有任何错误。但是,当我一次尝试25GB的数据时,我会得到以下错误。我试图了解如何避免以下失败。很高兴听到任何建议或想法 不同的错误Apache spark 处理大数据集时FetchFailedException或MetadataFetchFailedException,apache-spark,yarn,Apache Spark,Yarn,当我用1GB的数据集运行解析代码时,它就完成了,没有任何错误。但是,当我一次尝试25GB的数据时,我会得到以下错误。我试图了解如何避免以下失败。很高兴听到任何建议或想法 不同的错误 org.apache.spark.shuffle.MetadataFetchFailedException: Missing an output location for shuffle 0 org.apache.spark.shuffle.FetchFailedException: Failed to conne
org.apache.spark.shuffle.MetadataFetchFailedException: Missing an output location for shuffle 0
org.apache.spark.shuffle.FetchFailedException: Failed to connect to ip-xxxxxxxx
org.apache.spark.shuffle.FetchFailedException: Error in opening FileSegmentManagedBuffer{file=/mnt/yarn/nm/usercache/xxxx/appcache/application_1450751731124_8446/blockmgr-8a7b17b8-f4c3-45e7-aea8-8b0a7481be55/08/shuffle_0_224_0.data, offset=12329181, length=2104094}
群集详细信息:
纱线:8节核心总数:64
内存:500 GB
Spark版本:1.5 Spark提交声明:
spark-submit --master yarn-cluster \
--conf spark.dynamicAllocation.enabled=true \
--conf spark.shuffle.service.enabled=true \
--executor-memory 4g \
--driver-memory 16g \
--num-executors 50 \
--deploy-mode cluster \
--executor-cores 1 \
--class my.parser \
myparser.jar \
-input xxx \
-output xxxx \
堆栈跟踪之一:
at org.apache.spark.MapOutputTracker$$anonfun$org$apache$spark$MapOutputTracker$$convertMapStatuses$2.apply(MapOutputTracker.scala:460)
at org.apache.spark.MapOutputTracker$$anonfun$org$apache$spark$MapOutputTracker$$convertMapStatuses$2.apply(MapOutputTracker.scala:456)
at scala.collection.TraversableLike$WithFilter$$anonfun$foreach$1.apply(TraversableLike.scala:772)
at scala.collection.IndexedSeqOptimized$class.foreach(IndexedSeqOptimized.scala:33)
at scala.collection.mutable.ArrayOps$ofRef.foreach(ArrayOps.scala:108)
at scala.collection.TraversableLike$WithFilter.foreach(TraversableLike.scala:771)
at org.apache.spark.MapOutputTracker$.org$apache$spark$MapOutputTracker$$convertMapStatuses(MapOutputTracker.scala:456)
at org.apache.spark.MapOutputTracker.getMapSizesByExecutorId(MapOutputTracker.scala:183)
at org.apache.spark.shuffle.hash.HashShuffleReader.read(HashShuffleReader.scala:47)
at org.apache.spark.rdd.ShuffledRDD.compute(ShuffledRDD.scala:90)
at org.apache.spark.rdd.RDD.computeOrReadCheckpoint(RDD.scala:297)
at org.apache.spark.rdd.RDD.iterator(RDD.scala:264)
at org.apache.spark.rdd.MapPartitionsRDD.compute(MapPartitionsRDD.scala:38)
at org.apache.spark.rdd.RDD.computeOrReadCheckpoint(RDD.scala:297)
at org.apache.spark.rdd.RDD.iterator(RDD.scala:264)
at org.apache.spark.scheduler.ResultTask.runTask(ResultTask.scala:66)
at org.apache.spark.scheduler.Task.run(Task.scala:88)
at org.apache.spark.executor.Executor$TaskRunner.run(Executor.scala:214)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
at java.lang.Thread.run(Thread.java:745)
此错误几乎肯定是由执行器上的内存问题引起的。我可以想出几种方法来解决这类问题 1) 您可以尝试使用更多分区运行(在
数据帧上执行重新分区
)。当一个或多个分区包含的数据超过内存容量时,通常会出现内存问题
2) 我注意到您没有显式设置spark.Thread.executor.memoryOverhead
,因此它将默认设置为max(386,0.10*executorMemory)
,在您的情况下,该值将为400MB。对我来说这听起来很低。我会尝试将其增加到1GB(请注意,如果将memoryOverhead增加到1GB,则需要将执行器内存降低到3GB)
3) 查看故障节点上的日志文件。您要查找文本“Killing container”。如果您看到文本“超出物理内存限制运行”,根据我的经验,增加memoryOverhead将解决问题。通过将Spark timeoutSpark.network.timeout
增加到800这样的更大值,我也得到了一些好的结果。默认的120秒将导致很多执行者在重载时超时 好吧,这是一条老线索,关于Stackoverflow有很多答案,但我因为这个错误耽误了几天,我想分享这个故事可能会有所帮助
实际上有两种方法可以实现这一点。正如Glennie的回答所提到的,这很可能是内存问题,因此请确保您有足够的内存来存储所有内容。有容器内存、AM内存、映射内存、精简内存等配置需要注意。阅读有助于找到正确的配置。你应该自己选择数字,但这里有一些我设置的属性
纱线站点.xml
<property>
<name>yarn.nodemanager.resource.memory-mb</name>
<value>32768</value>
</property>
<property>
<name>yarn.app.mapreduce.am.resource.mb</name>
<value>4096</value>
</property>
<property>
<name>yarn.scheduler.minimum-allocation-mb</name>
<value>4096</value>
</property>
<property>
<name>mapreduce.map.memory.mb</name>
<value>4096</value>
</property>
<property>
<name>mapreduce.reduce.memory.mb</name>
<value>4096</value>
</property>
warn.nodemanager.resource.memory-mb
32768
warn.app.mapreduce.am.resource.mb
4096
warn.scheduler.minimum-allocation-mb
4096
mapred site.xml
<property>
<name>yarn.nodemanager.resource.memory-mb</name>
<value>32768</value>
</property>
<property>
<name>yarn.app.mapreduce.am.resource.mb</name>
<value>4096</value>
</property>
<property>
<name>yarn.scheduler.minimum-allocation-mb</name>
<value>4096</value>
</property>
<property>
<name>mapreduce.map.memory.mb</name>
<value>4096</value>
</property>
<property>
<name>mapreduce.reduce.memory.mb</name>
<value>4096</value>
</property>
mapreduce.map.memory.mb
4096
mapreduce.reduce.memory.mb
4096
这些可以修复您可能遇到的一些其他错误,例如PySparkShell在启动时崩溃。但是在我的例子中,虽然一些错误消失了(比如MetadataFetchFailed错误),但问题仍然存在。确切的错误是:
org.apache.spark.shuffle.FetchFailedException:无法连接到
DB-ETA-C/x.x.x:34085
在对从Spark超时到Thread shuffle服务的所有可能的Thread和Spark属性进行了研究之后,我最终意识到,在错误日志中,失败的容器正在查找本地(内部)的x.x.x
运行netstat-tulpn | grep时返回y.y.y.y:34085,其中y.y.y.y是外部IP地址。这根本不是内存问题,只是网络配置问题
Spark服务仅绑定到外部接口,因为主机名与/etc/hosts
中的外部IP相关联。更新/etc/hosts
文件后,问题得到解决
底线:
这个错误显然表明某些容器无法到达另一个容器。这通常是由于内存问题导致容器出现故障,但也可能是网络问题,因此也要注意这些问题,尤其是在节点上有多个接口的情况下。除了上述内存和网络配置问题外,值得注意的是,对于大型表(例如,这里有几个TB),org.apache.spark.shuffle.FetchFailedException可能由于检索随机分区超时而发生。要解决此问题,可以设置以下各项:
SET spark.reducer.maxReqsInFlight=1; -- Only pull one file at a time to use full network bandwidth.
SET spark.shuffle.io.retryWait=60s; -- Increase the time to wait while retrieving shuffle partitions before retrying. Longer times are necessary for larger files.
SET spark.shuffle.io.maxRetries=10;
如果所有洗牌任务都失败了,那么可能的原因是netty的依赖冲突。
从spark core中排除烦躁的依赖对我来说很有效
<dependency>
<groupId>org.apache.spark</groupId>
<artifactId>spark-core_2.10</artifactId>
<version>${spark.version}</version>
<exclusions>
<exclusion>
<groupId>io.netty</groupId>
<artifactId>netty-all</artifactId>
</exclusion>
<exclusion>
<groupId>io.netty</groupId>
<artifactId>netty</artifactId>
</exclusion>
</exclusions>
</dependency>
org.apache.spark
spark-core_2.10
${spark.version}
伊奥·内蒂
讨厌的
伊奥·内蒂
内蒂
这两个例外情况应单独讨论
对于MetadataFetchFailedException,它通常发生在一个执行器突然被终止或终止时,但这个执行器有一些无序输出,然后当另一个执行器尝试获取这个无序输出的元数据时,会发生异常
1) 在大多数情况下,这是由超过内存限制而被纱线杀死的容器造成的。因此,您需要在日志中再次确认这一点
2) 最常见的修复方法是增加memoryOverhead,默认值为0.1*执行器内存。这对于大多数情况来说太小了。我建议将其设置为0.2*执行器内存。如果有大量的执行者或运行另一个子进程,则需要更大的值
对于FetchFailedException,它通常发生在承载一些随机输出的执行器太忙或暂时死机时。这可能是由于磁盘IO或网络IO速度较慢造成的。当你有超过1000名遗嘱执行人时,这可能很常见
1) 你需要检查的第一件事是这个遗嘱执行人是否真的死了。您可以在死执行器列表中确认这一点。然后检查死亡执行者的日志
2) 当有1000个执行器时,最坏的情况是一个执行器最多可能有1000吨