理解作业基本原理,是进行Spark作业资源参数调优的基本前提。Spark作业基础概念与运行流程
以下记录下常见参数配置:
num-executors:用于设置Spark作业总共要用多少个Executor进程来执行。Driver在向YARN集群资源管理器申请资源时,YARN会尽可能按照该属性值来在集群的各个工作节点上启动相应数量的Executor进程。如果不设置,默认只会启动少量的Executor进程,可能导致Spark作业运行速度非常慢。
executor-memory:用于设置每个Executor进程的内存。注意,num-executors * executor-memory的值是不能超过指定资源队列的最大内存值。一般情况下最好不要超过资源队列最大总内存的1/3~1/2,避免Spark作业占用了队列所有的资源。
executor-cores:用于设置每个Executor进程的CPU core数量。该属性值决定了每个Executor进程并行执行Task线程的能力。因为每个CPU core同一时间只能执行一个task线程,因此每个Executor进程的CPU core数量越多,越能够快速地执行完分配给自己的所有task线程。
注意,需要根据资源队列的最大CPU core数,再依据设置的Executor数量,来决定每个Executor进程可以分配到几个CPU Core。一般情况下建议num-executors * executor-cores不要超过队列总CPU core的1/3~1/2。
Yarn集群能够最多并行的Task数为 spark.executor.instances * executor-cores。
driver-memory:用于设置Driver进程的内存。注意:如果需要将RDD的数据全部拉取到Driver上进行处理,那么必须确保Driver的内存足够大,否则会出现OOM内存溢出的问题。例如collect算子。
spark.executor.instances:该参数决定了yarn集群中,最多能够同时启动的EXECUTOR的实例个数。Yarn中实际能够启动的最大Executors的数量会小于等于该值。如果不能确定最大能够启动的Executors数量,建议将该值先设置的足够大。(就是设置尽量大)
spark.default.parallelism:用于设置每个stage的默认task数量。注意,Spark作业的默认task数量为500~1000个较为合适。如果不设置该参数那么就会导致Spark根据底层HDFS的block数量来设置task的数量,默认是一个HDFS block对应一个task。通常来说,Spark默认设置的数量是偏少的(比如就几十个task),如果task数量偏少的话,就会导致前面设置好的Executor的参数都前功尽弃。既可能存在部分Executor进程可能根本就没有task执行,也就是白白浪费了资源!因此Spark官网建议的设置原则是,设置该参数为num-executors * executor-cores的2~3倍较为合适,比如Executor的总CPU core数量为300个,那么设置1000个task是可以的,此时可以充分地利用Spark集群的资源。
spark.storage.memoryFraction:用于设置RDD持久化数据在Executor内存中能占的比例,默认是0.6。即默认Executor 60%的内存,可以用来保存持久化的RDD数据。注意,如果Spark作业中有较多的RDD持久化操作,该参数的值可以适当提高一些,保证持久化的数据能够容纳在内存中。避免内存不够缓存所有的数据,导致数据只能写入磁盘中,降低了性能。但是如果Spark作业中的shuffle类操作比较多,而持久化操作比较少,那么这个参数的值适当降低一些比较合适。此外,如果发现作业由于频繁的gc导致运行缓慢(通过spark web ui可以观察到作业的gc耗时),意味着task执行用户代码的内存不够用,那么同样建议调低这个参数的值。
spark.shuffle.memoryFractions:用于设置shuffle过程中一个task拉取到上个stage的task的输出后,进行聚合操作时能够使用的Executor内存的比例,默认是0.2。也就是说,Executor默认只有20%的内存用来进行该操作。shuffle操作在进行聚合时,如果发现使用的内存超出了这个20%的限制,那么多余的数据就会溢写到磁盘文件中去,此时就会极大地降低性能。
注意,如果Spark作业中的RDD持久化操作较少,shuffle操作较多时,建议降低持久化操作的内存占比,提高shuffle操作的内存占比比例,避免shuffle过程中数据过多时内存不够用,必须溢写到磁盘上,降低了性能。此外,如果发现作业由于频繁的gc导致运行缓慢,意味着task执行用户代码的内存不够用,那么同样建议调低这个参数的值。
spark-submit \
--master yarn \
--deploy-mode client \
--driver-memory 2G \
--queue gis \
--num-executors 6 \
--executor-cores 6 \
--executor-memory 8G \
--class com.test.AnalysisDiffElevator \
--verbose \
--conf spark.default.parallelism=1000 \
./test-1.0-SNAPSHOT.jar
spark.sql.queryExecutionListeners,org.apache.spark.sql.hive.DagUsageListener
spark.hadoop.yarn.timeline-service.enabled,false
spark.driver.memory,2G
spark.executor.memory,8G
spark.executor.instances,6
spark.eventLog.enabled,true
spark.sql.result.partition.ratio,0.8
spark.serializer,org.apache.spark.serializer.KryoSerializer
spark.yarn.executor.memoryOverhead,2G
spark.kryoserializer.buffer.max,1111m
spark.submit.deployMode,client
spark.driver.maxResultSize,1111
spark.extraListeners,org.apache.spark.sql.hive.DagUsageListener
spark.master,yarn
spark.port.maxRetries,999
spark.executor.cores,6
待续补充。。。。
https://www.cnblogs.com/hejunhong/p/12571690.html