Spark学习笔记

如何为Spark应用程序分配--num-executors,--

2019-03-28  本文已影响0人  LestatZ

前言

在我们提交spark程序时,应该如何为Spark集群配置--num-executors, - executor-memory和--execuor-cores 呢?

一些资源参数设置的基本知识

简单来说,有以下两个公式:

<table align=left><tr><td align=left>每个executor从YARN请求的内存 = <b>spark-executor-memory + spark.yarn.executor.memoryOverhead </td></tr></table>
<table align=left><tr><td align=left> spark.yarn.executor.memoryOverhead = <b>Max(384MB, 7% of spark.executor-memory)

例如当我设置 --executor-memory=20时, 我们实际请求了

         20GB + memoryOverhead = 20 + 7% of 20GB = ~23GB。

运行具有executors大内存的通常会导致<font color=black><b>过多的GC延迟。</font>

运行较小的executors(例如,1G & 1 CPU core)则会浪费 ==单个JVM中运行多个任务==所带来的优点。

不同配置的优劣分析

现在,假设我们的集群配置如下
<table align=left><tr><td align=left>
10 Nodes

16 cores per Node

64GB RAM per Node
</td></tr></table>

第一种方法:使用较小的executors
`--num-executors` = `在这种方法中,我们将为每个核心分配一个executor`
                  = `集群的总核心数`
                  = `每个节点的核心数 * 集群的总节点数` 
                  =  16 x 10 = 160
                  
`--executor-cores`  = 1 (`每个executor分配的核心数目`)

`--executor-memory` = `每个executor分配的内存数`
                    = `每个节点内存总数数/每个节点上分配的executor数`
                    = 64GB/16 = 4GB

分析
由于每个executor只分配了一个核,我们将无法利用在同一个JVM中运行多个任务的优点。 此外,共享/缓存变量(如广播变量和累加器)将在节点的每个核心中复制16次。 最严重的就是,我们没有为Hadoop / Yarn守护程序进程留下足够的内存开销,我们还忘记了将ApplicationManagers运行所需要的开销加入计算。

第二种方法:使用较大的executors
`--num-executors` = `在这种方法中,我们将为每个节点分配一个executor`
                  = `集群的总节点数`
                  = 10
                    
`--executor-cores` = `每个节点一个executor意味着该节点的所有核心都分配给一个执executor`
                   = `每个节点的总核心数`
                   = 16
                     
`--executor-memory` = `每个executor分配的内存数`
                    = `每个节点内存总数数/每个节点上分配的executor数`
                    = 64GB/1 = 64GB

分析:
每个executor都有16个核心,由于HDFS客户端遇到大量并发线程会出现一些bug,即HDFS吞吐量会受到影响。同时过大的内存分配也会导致过多的GC延迟。

第三种方法:使用优化的executors

参考资料
how-to-tune-your-apache-spark-jobs-part-2
distribution_of_executors_cores_and_memory_for_spark_application

上一篇 下一篇

猜你喜欢

热点阅读