欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

提交Spark作业 | 科学设定spark-submit参数

程序员文章站 2024-02-21 18:58:28
...

点击上方蓝色字体,选择“设为星标”

回复”资源“获取更多惊喜

提交Spark作业 | 科学设定spark-submit参数

提交Spark作业 | 科学设定spark-submit参数

大数据技术与架构

点击右侧关注,大数据开发领域最强公众号!

提交Spark作业 | 科学设定spark-submit参数

提交Spark作业 | 科学设定spark-submit参数

大数据真好玩

点击右侧关注,大数据真好玩!

提交Spark作业 | 科学设定spark-submit参数

首先摆出我们常用的一种设定。

bin/spark-submit \
--class com.xyz.bigdata.calendar.PeriodCalculator \
--master yarn \
--deploy-mode cluster \
--queue default_queue \
--num-executors 50 \
--executor-cores 2 \
--executor-memory 4G \
--driver-memory 2G \
--conf "spark.default.parallelism=250" \
--conf "spark.shuffle.memoryFraction=0.3" \
--conf "spark.storage.memoryFraction=0.5" \
--conf "spark.driver.extraJavaOptions=-XX:+UseG1GC" \
--conf "spark.executor.extraJavaOptions=-XX:+UseG1GC" \
--verbose \
${PROJECT_DIR}/bigdata-xyz-0.1.jar

关于spark-submit的执行过程,读Spark Core的源码能够获得一个大致的印象。

  • num-executors

含义:设定Spark作业要用多少个Executor进程来执行。

设定方法:根据我们的实践,设定在30~100个之间为最佳。如果不设定,默认只会启动非常少的Executor。如果设得太小,无法充分利用计算资源。设得太大的话,又会抢占集群或队列的资源,导致其他作业无法顺利执行。

  • executor-cores

含义:设定每个Executor能够利用的CPU核心数(这里核心指的是vCore)。核心数越多,并行执行Task的效率也就越高。

设定方法:根据我们的实践,设定在2~6之间都是可以的,主要是根据业务类型和数据处理逻辑的复杂程度来定,一般来讲设2或者3就够用了。需要注意的是,num-executors * executor-cores不能将队列中的CPU资源耗尽,最好不要超过总vCore数的1/3,以给其他作业留下剩余资源。

  • executor-memory

含义:设定每个Executor的内存量(堆内内存)。这个参数比executor-cores更为重要,因为Spark作业的本质就是内存计算,内存的大小直接影响性能,并且与磁盘溢写、OOM等都相关。

设定方法:一般设定在2G~8G之间,需要根据数据量慎重做决定。如果作业执行非常慢,出现频繁GC或者OOM,就得适当调大内存。并且与上面相同,num-executors * executor-memory也不能过大,最好不要超过队列总内存量的一半。

另外,还有一个配置项spark.executor.memoryOverhead,用来设定每个Executor可使用的堆外内存大小,默认值是executor-memory的0.1倍,最小值384M。一般来讲都够用,不用特意设置。

  • driver-memory

含义:设定Driver进程的内存量(堆内内存)。

设定方法:由于我们几乎不会使用collect()之类的算子把大量RDD数据都拉到Driver上来处理,所以它的内存可以不用设得过大,2G可以应付绝大多数情况。但是,如果Spark作业处理完后数据膨胀比较多,那么还是应该酌情加大这个值。与上面一项相同,spark.driver.memoryOverhead用来设定Driver可使用的堆外内存大小。

  • spark.default.parallelism

含义:对于shuffle算子,如reduceByKey()或者join(),这个参数用来指定父RDD中最大分区数。由于分区与Task有一一对应关系,因此也可以理解为Task数。其名称的字面意义是“并行度”,不能直接表达出这种含义。

设定方法:Spark官方文档中推荐每个CPU core执行23个Task比较合适,因此这个值要设定为(num-executors * executor-cores)的23倍。这个参数同样非常重要,因为如果不设定的话,分区数就会由RDD本身的分区来决定,这样往往会使得计算效率低下。

  • spark.shuffle.memoryFraction

含义:shuffle操作(聚合、连接、分组等等)能够使用的可用堆内存(堆大小减去300MB保留空间)的比例,默认值是0.2。如果shuffle阶段使用的内存比例超过这个值,就会溢写到磁盘。

设定方法:取决于计算逻辑中shuffle逻辑的复杂度,如果会产生大量数据,那么一定要调高。在我们的实践中,一般都设定在0.3左右。但是,如果调太高之后发现频繁GC,那么就是执行用户代码的execution内存不够用了,适当降低即可。

  • spark.storage.memoryFraction

含义:缓存操作(persist/cache)能够使用的可用堆内存的比例,默认值是0.6。

设定方法:如果经常需要缓存非常大的RDD,那么就需要调高。否则,如果shuffle操作更为重量级,适当调低也无妨。我们一般设定在0.5左右。

其实,spark.shuffle/storage.memoryFraction是旧版的静态内存管理(StaticMemoryManager)的遗产。在Spark 1.6版本之后的文档中已经标记成了deprecated。目前取代它们的是spark.memory.fraction和spark.memory.storageFraction这两项,参考新的统一内存管理(UnifiedMemoryManager)机制可以得到更多细节。前者的含义是总内存占堆的比例,即execution+storage+shuffle内存的总量。后者则是storage内存占前者的比例。默认值分别为0.75(最新版变成了0.6)和0.5。

  • spark.driver/executor.extraJavaOptions

含义:Driver或Executor进程的其他JVM参数。

设定方法:一般可以不设置。如果设置,常见的情景是使用-Xmn加大年轻代内存的大小,或者手动指定垃圾收集器(最上面的例子中使用了G1,也有用CMS的时候)及其相关参数。

一句话总结 spark-submit参数的设定有一定的准则可循,但更多地是根据实际业务逻辑和资源余量进行权衡。

提交Spark作业 | 科学设定spark-submit参数

提交Spark作业 | 科学设定spark-submit参数

版权声明:

本文为《大数据真好玩》整理,原作者独家授权。未经原作者允许转载追究侵权责任。

编辑|冷眼丶

微信公众号|大数据真好玩

文章不错?点个【在看】吧! ????