我正在使用hdp2.5,运行spark submit作为Yarn簇模式。
我尝试使用Dataframe交叉连接生成数据。即
val generatedData = df1.join(df2).join(df3).join(df4)
generatedData.saveAsTable(...)....
df1存储级别是内存和磁盘
df2、df3、df4存储级别仅为内存单元
df1有更多的记录,即500万条,而df2到df4最多有100条记录。使用broadcastednestedloopjoin解释计划这样做,explain plain将获得更好的性能。
因为某些原因它总是失败。我不知道如何调试它,内存在哪里爆炸。
错误日志输出:
16/12/06 19:44:08 WARN YarnAllocator: Container marked as failed: container_e33_1480922439133_0845_02_000002 on host: hdp4. Exit status: 143. Diagnostics: Container killed on request. Exit code is 143
Container exited with a non-zero exit code 143
Killed by external signal
16/12/06 19:44:08 WARN YarnSchedulerBackend$YarnSchedulerEndpoint: Container marked as failed: container_e33_1480922439133_0845_02_000002 on host: hdp4. Exit status: 143. Diagnostics: Container killed on request. Exit code is 143
Container exited with a non-zero exit code 143
Killed by external signal
16/12/06 19:44:08 ERROR YarnClusterScheduler: Lost executor 1 on hdp4: Container marked as failed: container_e33_1480922439133_0845_02_000002 on host: hdp4. Exit status: 143. Diagnostics: Container killed on request. Exit code is 143
Container exited with a non-zero exit code 143
Killed by external signal
16/12/06 19:44:08 WARN TaskSetManager: Lost task 1.0 in stage 12.0 (TID 19, hdp4): ExecutorLostFailure (executor 1 exited caused by one of the running tasks) Reason: Container marked as failed: container_e33_1480922439133_0845_02_000002 on host: hdp4. Exit status: 143. Diagnostics: Container killed on request. Exit code is 143
Container exited with a non-zero exit code 143
Killed by external signal
在此错误之前,我没有看到任何警告或错误日志。有什么问题?我应该在哪里查找内存消耗?我在斯巴奎的储存标签上看不到任何东西。日志取自hdp2.5上的yarn资源管理器ui
编辑查看容器日志,它似乎是一个 java.lang.OutOfMemoryError: GC overhead limit exceeded
我知道如何增加记忆,但我已经没有记忆了。如何使用4个Dataframe执行笛卡尔/乘积联接而不出现此错误。
3条答案
按热度按时间iq3niunx1#
原因1
默认情况下,洗牌计数为
200
. 洗牌太多会增加程序的复杂性和崩溃的几率。尝试控制spark会话中的洗牌次数。我把计数改为5
使用下面的代码。另外,如果您使用的是Dataframe,并且没有对Dataframe进行重新分区,那么执行将在单个执行器中完成。如果只有一个执行器运行一段时间,那么Yarn将使其他执行器关闭。稍后如果需要更多内存,尽管yarn尝试重新调用其他执行器,但有时执行器不会出现,因此进程可能会失败,并出现内存溢出问题。要克服这种情况,请尝试在调用操作之前重新划分Dataframe。
请注意,您可能需要根据您的需求更改随机播放和分区计数。在我的情况下,上面的组合是有效的。
原因2
可能是由于内存未及时清除。例如,如果您正在使用scala运行spark命令,并且正在执行一堆sql语句并导出到csv。某些配置单元表中的数据将非常庞大,您必须管理代码中的内存。
例如,考虑下面的代码
lst_Sqls
是包含一组sql命令的列表当你运行这个命令时,有时你会看到同样的错误。这是因为虽然spark清除内存,但它是以一种懒惰的方式进行的,即,您的循环将继续,但spark可能会在稍后的某个时间清除内存。
在这种情况下,您需要管理代码中的内存,即在执行每个命令后清除内存。为此,让我们稍微修改一下代码。我已经在下面的代码中注解了每一行的作用。
btqmn9zl2#
所有容器和am的日志文件都可以在,
如果你只想要am日志,
如果你想找到为这个任务运行的容器,
如果你只需要一个容器日志,
要使这些命令正常工作,必须将日志聚合设置为true,否则必须从各个服务器目录获取日志。
更新除了尝试交换之外,您什么也做不了,但这会降低性能很多。
gc开销限制意味着,gc一直连续不停地运行,但无法恢复太多内存。唯一的原因是,要么代码写得很差,并且有大量的反向引用(这是值得怀疑的,因为您正在进行简单的连接),要么内存容量已经达到。
nwlls2ji3#
我也遇到了这个问题,并试图通过参考一些博客来解决它。1.运行spark add conf bellow:
当使用jvm gc时,您将收到以下消息:
psyounggen和paroldgen都是99%,那么您将得到java.lang.outofmemoryerror:如果创建了更多对象,则超出了gc开销限制。
当有更多内存资源可用时,尝试为执行器或驱动程序添加更多内存:
--执行器内存10000m
--驾驶员记忆10000m
对于我的例子:psyounggen的内存比paroldgen小,这导致许多年轻对象进入paroldgen内存区域,最后paroldgen不可用。因此java.lang.outofmemoryerror:java堆空间错误出现。
正在为执行者添加conf:
'spark.executor.extrajavaoptions=-xx:newratio=1-xx:+usecompressedoops-verbose:gc -xx:+printgcdetails-xx:+printgctimestamps'
-xx:newratio=费率=paroldgen/psyounggen
它依赖于。你可以尝试gc策略,比如
java并发并行gc
如果第4步和第6步都完成了,但仍然出现错误,您应该考虑更改代码。例如,减少ml模型中的迭代器时间。