Spark任务参数优化
当我们提交Spark作业的时候,Spark作业会启动Driver进程去运行Application的main()函数,并且创建SparkContext,然后通过SparkContext与集群管理器申请Spark作业所需的资源,即Spark作业所需要的Executor进程。集群管理器会根据提交作业的资源参数设置,为各个工作节点分配相应数量的Executor,以及每个Executor所占用的内存数量和CPU Core核心数。
当资源分配完成以后,Driver便会开始运行我们的作业代码,过程中,Driver会将我们的Spark作业根据逻辑拆解为多个stage,并将每个stage拆分为多个最小计算单元task,分配到各个Executor上去执行。当一个Stage的所有task执行完毕后,便会开始下一个stage的调度,直到我们的作业代码执行完毕。
在作业的运行过程中,Executor主要占用的资源分别是Cpu核心数和内存大小,合理的分配资源的大小,可以有效的提高我们的作业执行效率。
我们的Cpu的每一个core在同一时间只能执行一个线程,而我们的Excutor每次都会接收到多个task任务,每个task任务会占用一个线程,Excutor以多线程并发形式运行,众所周知,线程数量并非越多越好,只有当Cpu核心数与线程数数量相对合理,才能更加高效的处理task任务。
内存方面,Executor的内存主要分为三块,分别是执行task任务所需的内存,获取之前stage输出的内存,以及RDD持久化所需要的内存,默认占比为2:2:6。
当了解了Spark的运行原理以及资源的使用方式以后,我们就可以通过修改Spark提供的资源参数,设置Spark作业的资源分配,以达到性能的优化。主要参数配置如下:
1. num-executors
excutor的个数:需要根据现有资源的大小情况进行合理配置,在考虑每个excutor的内存和核心数情况下,设置合理的个数以免资源的浪费。
2. executor-memory
executor的内存大小:考虑作业情况不要设置的过小,过小可能会造成JVM OOM异常,占用的内存总量为num-executors*excutor-memory,需要注意不要超过当前资源的最大内存总量。
3. executor- cores
executor的单个core核心个数:在资源允许的情况下Excutor的核心数越多,作业的执行效率就会越高,占用的Cpu core总量为num-executors*excutor-cores,需要注意不要超过当前资源Cpu cores的总数。
4. spark.default.parallelism
stage划分的task个数:task个数可以根据你设置的Executor的个数和Cpu核心数进行设置,一般推荐为num-executors*executor-cores的2~3倍。
5. spark.shuffle.memoryFraction
shuffle操作内存在Executor内存中的占比:默认值为0.2,即0.2*executor-memory的内存会被用来处理shuffle操作的数据,当内存不够的时候,会将数据写入磁盘保存,从而导致性能降低,当shuffle操作较多时,可以提高该占比。
6. spark.storage.memoryFraction
持久化操作内存在Executor内存中的占比:默认值为0.6,即0.6*executor-memory的内存会被用来保存持久化的RDD的数据,当内存不够的时候,会将数据写入磁盘保存,从而导致性能降低,当持久化操作较多时,可以提高该占比。
7. driver-memory
driver进程的内存大小:一般使用默认值即可,当Driver上的数据过多出现内存溢出的情况下,需要调整该参数。
- 点赞
- 收藏
- 关注作者
评论(0)