Spark: 执行器内存超过物理限制

4

我的输入数据集大约有150G。 我正在设置

--conf spark.cores.max=100 
--conf spark.executor.instances=20 
--conf spark.executor.memory=8G 
--conf spark.executor.cores=5 
--conf spark.driver.memory=4G

但是由于数据在执行器之间分配不均,我一直遇到这个问题:

Container killed by YARN for exceeding memory limits. 9.0 GB of 9 GB physical memory used

以下是我的问题:

1. Did I not set up enough memory in the first place? I think 20 * 8G > 150G, but it's hard to make perfect distribution, so some executors will suffer
2. I think about repartition the input dataFrame, so how can I determine how many partition to set? the higher the better, or?
3. The error says "9 GB physical memory used", but i only set 8G to executor memory, where does the extra 1G come from?

谢谢你!

您正在将Spark执行器实例设置为20。这意味着您将启动20个每个8G的执行器,如果我没记错的话。您能否尝试减少它们然后再试一下?将其减少到1将是一个开始。 - ar7
您好,如果我将执行器数量减少到1,那么我只有一个带有8G内存的执行器,这时150G的输入数据无法容纳。 - user2628641
可能是因为yarn容器没有配置足够的内存。你面临的错误的可能解决方案是什么?https://dev59.com/eVwZ5IYBdhLWcg3wG9F_#33118489和http://m.blog.csdn.net/article/details?id=50387104 - ar7
2个回答

5
使用Yarn时,还有一个设置影响要为执行器请求多大的yarn容器:
spark.yarn.executor.memoryOverhead

默认值为您执行器内存设置的0.1倍。它定义了除您指定的执行器内存外要请求多少额外的开销内存。首先尝试增加这个数字。

另外,一个Yarn容器不能给你任意大小的内存。它只会返回分配了内存大小为其最小分配大小的倍数的容器,该最小分配大小由此设置控制:

yarn.scheduler.minimum-allocation-mb

将其设置为较小的数字将减少您超过所需数量的风险。我通常还会将下面的键值设置为大于所需容器大小的值,以确保Spark请求控制执行程序的大小,而不是Yarn踩在它们上面。这是Yarn提供的最大容器大小。
nodemanager.resource.memory-mb

4
9GB由8GB的执行器内存和作为参数添加的spark.yarn.executor.memoryOverhead组成,该参数设置为.1,因此容器的总内存为spark.yarn.executor.memoryOverhead + (spark.yarn.executor.memoryOverhead * spark.yarn.executor.memoryOverhead),即8GB + (.1 * 8GB) ≈ 9GB
您可以使用单个执行器运行整个过程,但这将需要很长时间。要理解这一点,您需要了解分区和任务的概念。分区的数量由输入和操作定义。例如,如果您从hdfs读取一个150gb的csv文件,并且您的hdfs块大小为128mb,则最终会得到150 * 1024 / 128 = 1200个分区,这直接映射到Spark UI中的1200个任务。
每个任务将由执行器接手。您不需要在内存中一直保存所有的150GB数据。例如,当您只有一个执行器时,显然您无法从Spark的并行能力中受益,但它将从第一个任务开始处理数据,并将其保存回dfs,然后开始处理下一个任务。
您应该检查以下内容:
- 输入分区有多大?输入文件是否可拆分?如果单个执行器必须加载大量内存,则肯定会耗尽内存。 - 您正在执行什么样的操作?例如,如果您使用非常低的基数进行连接,则会得到大量分区,因为具有特定值的所有行都将位于同一个分区中。 - 是否执行了非常昂贵或低效的操作?例如笛卡尔积等。
希望这可以帮助您。愉快的Spark之旅!

2
我认为你想说的是executor-memory + (spark.yarn.executor.memoryOverhead * executor-memory),即8GB + (.1 * 8GB) ≈ 9GB。 - altayseyhan

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接