Skip to main content

学习一个Spark内存的管理案例

分类:  Azure Databricks 标签:  #Azure #Databricks 发布于: 2023-06-18 19:56:24

在学习Databricks的内存管理时,我发现在stackoverflow上有一篇非常好的案例,我总结了一下这个案例并分享给大家。

用户场景

用户在本机写了一个Spark的应用。这个应用从本地读取14KB的文本文件,读入Spark之后,然后对这部分数据进行一定的转换操作,最后存储到数据库中。
使用的环境是: 8个Core,16G物理内存。 Java max heap size被设为了12G.

然后用户使用如下的命令提交任务到Spark本地执行:

bin/spark-submit --class com.myapp.application --master local[*] --executor-memory 2G --driver-memory 4G /jars/application.jar

然后用户看到Spark一直输出:

 [Executor task launch worker-8hread] WARN org.apache.spark.storage.MemoryStore - Not enough space to cache rdd_57_0 in memory! (computed 26.4 MB so far)

用户很苦恼问题到底在哪里。

解答

解答之前我们先考虑一个知识点,就是如何在Spark的应用中设置java max heap size, 我相信一提到这个,大家一定会想起来JVM的设置参数,例如-Xmx 可以用户设置最大的内存,同时检查Spark的配置,它有一个参数可以用于传入JVM的通用设置,这个参数就是spark.executor.extraJavaOptions, 因此很多人就会想到使用这个参数,传入设置-Xmx, -Xms来配置java max heap size, 但是实际上在Spark这一侧,这是一个错误。

你可以参看Spark的官方配置文档,这个文档说得特别清楚:

Note that it is illegal to set Spark properties or maximum heap size (-Xmx) settings with this option. Spark properties should be set using a SparkConf object or the spark-defaults.conf file used with the spark-submit script. Maximum heap size settings can be set with spark.executor.memory.

也就是说这么设置是不允许的,Java max Heap Size是通过spark.executor.memory来设置的(针对executor), 针对Driver是通过Spark.driver.memory来设置的。

回到我们这个用户的案例,这个用户是在本地运行Spark,也就是在非集群模式上运行,这对于学习是可以的,但是有几个点需要注意:

  1. 在本地模式下是无需使用参数spark.driver.memory的。
  2. 在本地模式下由于worker和driver是运行在同一个jvm process里,因此实际上在本地模式下spark.executor.memory参数也是没有意义的。
  3. 在本地模式下应该是使用spark-shell而非spark-submit

不清楚这个用户是如何设定了java max heap size到12G的,假定是通过jvm的运行参数,用户的总共内存才16G, java max heap size = 12G,execute momroy 4 G, 2G设为了driver, 同时通过了spark-submit来提交,这势必导致仅仅只有16G内存的机器在运行Spark应用时,内存不足。

因此最为正确的做法是:

bin/spark-submit --class com.myapp.application --master local[*] /jars/application.jar

本地运行不指定任何参数,就不会有这样的报错了。