Spark中Task,Partition,RDD、节点数、Executor数、core数目的关系和Application,Driver,Job,Task,Stage理解
梳理一下Spark中关于并发度涉及的几个概念File,Block,Split,Task,Partition,RDD以及节点数、Executor数、core数目的关系。
输入可能以多个文件的形式存储在HDFS上,每个File都包含了很多块,称为Block。
当Spark读取这些文件作为输入时,会根据具体数据格式对应的InputFormat进行解析,一般是将若干个Block合并成一个输入分片,称为InputSplit,注意InputSplit不能跨越文件。
随后将为这些输入分片生成具体的Task。InputSplit与Task是一一对应的关系。
随后这些具体的Task每个都会被分配到集群上的某个节点的某个Executor去执行。
- 每个节点可以起一个或多个Executor。
- 每个Executor由若干core组成,每个Executor的每个core一次只能执行一个Task。
- 每个Task执行的结果就是生成了目标RDD的一个partiton。
注意: 这里的core是虚拟的core而不是机器的物理CPU核,可以理解为就是Executor的一个工作线程。
而 Task被执行的并发度 = Executor数目 * 每个Executor核数。
至于partition的数目:
- 对于数据读入阶段,例如sc.textFile,输入文件被划分为多少InputSplit就会需要多少初始Task。
- 在Map阶段partition数目保持不变。
- 在Reduce阶段,RDD的聚合会触发shuffle操作,聚合后的RDD的partition数目跟具体操作有关,例如repartition操作会聚合成指定分区数,还有一些算子是可配置的。
1,Application
application(应用)其实就是用spark-submit提交的程序。比方说spark examples中的计算pi的SparkPi。一个application通常包含三部分:从数据源(比方说HDFS)取数据形成RDD,通过RDD的transformation和action进行计算,将结果输出到console或者外部存储(比方说collect收集输出到console)。
2,Driver
Spark中的driver感觉其实和yarn中Application Master的功能相类似。主要完成任务的调度以及和executor和cluster manager进行协调。有client和cluster联众模式。client模式driver在任务提交的机器上运行,而cluster模式会随机选择机器中的一台机器启动driver。从spark官网截图的一张图可以大致了解driver的功能。
3,Job
Spark中的Job和MR中Job不一样不一样。MR中Job主要是Map或者Reduce Job。而Spark的Job其实很好区别,一个action算子就算一个Job,比方说count,first等。
4, Task
Task是Spark中最新的执行单元。RDD一般是带有partitions的,每个partition的在一个executor上的执行可以任务是一个Task。
5, Stage
Stage概念是spark中独有的。一般而言一个Job会切换成一定数量的stage。各个stage之间按照顺序执行。至于stage是怎么切分的,首选得知道spark论文中提到的narrow dependency(窄依赖)和wide dependency( 宽依赖)的概念。其实很好区分,看一下父RDD中的数据是否进入不同的子RDD,如果只进入到一个子RDD则是窄依赖,否则就是宽依赖。宽依赖和窄依赖的边界就是stage的划分点
参数列表如下所示:
--class org.apache.spark.examples.SparkPi --master yarn --deploy-mode client --driver-memory 4g --num-executors 2 --executor-memory 2g --executor-cores 2 /opt/apps/spark-1.6.0-bin-hadoop2.6/lib/spark-examples*.jar 10
参数说明如下所示:
参数 | 参考值 | 说明 |
---|---|---|
class | org.apache.spark.examples.SparkPi | 作业的主类。 |
master | yarn | 因为 E-MapReduce 使用 yarn 的模式,所以这里只能是 yarn 模式。 |
yarn-client | 等同于 –-master yarn —deploy-mode client, 此时不需要指定deploy-mode。 | |
yarn-cluster | 等同于 –-master yarn —deploy-mode cluster, 此时不需要指定deploy-mode。 | |
deploy-mode | client | client 模式表示作业的 AM 会放在 Master 节点上运行。要注意的是,如果设置这个参数,那么需要同时指定上面 master 为 yarn。 |
cluster | cluster 模式表示 AM 会随机的在 worker 节点中的任意一台上启动运行。要注意的是,如果设置这个参数,那么需要同时指定上面 master 为yarn。 | |
driver-memory | 4g | driver 使用的内存,不可超过单机的 core 总数。 |
num-executors | 2 | 创建多少个 executor。 |
executor-memory | 2g | 各个 executor 使用的最大内存,不可超过单机的最大可使用内存。 |
executor-cores | 2 | 各个 executor 使用的并发线程数目,也即每个 executor 最大可并发执行的 Task 数目。 |
资源计算
在不同模式、不同的设置下运行时,作业使用的资源情况如下表所示:
-
yarn-client 模式的资源计算
节点 资源类型 资源量(结果使用上面的例子计算得到) master core 1 mem driver-memroy = 4G worker core num-executors * executor-cores = 4 mem num-executors * executor-memory = 4G - 作业主程序(Driver 程序)会在 master 节点上执行。按照作业配置将分配 4G(由 —driver-memroy 指定)的内存给它(当然实际上可能没有用到)。
- 会在 worker 节点上起 2 个(由 —num-executors 指定)executor,每一个 executor 最大能分配 2G(由 —executor-memory 指定)的内存,并最0大支持 2 个(由—executor-cores 指定)task 的并发执行。
-
yarn-cluster 模式的资源计算
节点 资源类型 资源量(结果使用上面的例子计算得到) master 一个很小的 client 程序,负责同步 job 信息,占用很小。 worker core num-executors * executor-cores+spark.driver.cores = 5 mem num-executors * executor-memory + driver-memroy = 8g 说明 这里的 spark.driver.cores 默认是 1,也可以设置为更多。
资源使用的优化
-
yarn-client 模式
若您有了一个大作业,使用 yarn-client 模式,想要多用一些这个集群的资源,请参见如下配置:
--master yarn-client --driver-memory 5g –-num-executors 20 --executor-memory 4g --executor-cores 4
注意
- Spark 在分配内存时,会在用户设定的内存值上溢出 375M 或 7%(取大值)。
- Yarn 分配 container 内存时,遵循向上取整的原则,这里也就是需要满足 1G 的整数倍。
按照上述的资源计算公式,
- master 的资源量为:
- core:1
- mem:6G (5G + 375M 向上取整为 6G)
- workers 的资源量为:
- core: 20*4 = 80
- mem: 20*5G (4G + 375M 向上取整为 5G) = 100G
可以看到总的资源没有超过集群的总资源,那么遵循这个原则,您还可以有很多种配置,例如:
--master yarn-client --driver-memory 5g --num-executors 40 --executor-memory 1g --executor-cores 2
--master yarn-client --driver-memory 5g --num-executors 15 --executor-memory 4g --executor-cores 4
--master yarn-client --driver-memory 5g --num-executors 10 --executor-memory 9g --executor-cores 6
原则上,按照上述的公式计算出来的需要资源不超过集群的最大资源量就可以。但在实际场景中,因为系统,hdfs 以及 E-MapReduce 的服务会需要使用 core 和 mem 资源,如果把 core 和 mem 都占用完了,反而会导致性能的下降,甚至无法运行。
executor-cores 数一般也都会被设置成和集群的可使用核一致,因为如果设置的太多,CPU 会频繁切换,性能并不会提高。
-
yarn-cluster 模式
当使用 yarn-cluster 模式后,Driver 程序会被放到 worker 节点上。资源会占用到 worker 的资源池里面,这时若想要多用一些这个集群的资源,请参加如下配置:
--master yarn-cluster --driver-memory 5g --num-executors 15 --executor-memory 4g --executor-cores 4
./bin/spark-shell --master yarn --deploy-mode client --num-executors 2 --executor-cores 3
参数解释
1.num-executors
参数说明:
该参数用于设置Spark作业总共要用多少个Executor进程来执行。Driver在向YARN集群管理器申请资源时,YARN集群管理器会尽可能按照你的设置来在集群的各个工作节点上,启动相应数量的Executor进程。这个参数非常之重要,如果不设置的话,默认只会给你启动少量的Executor进程,此时你的Spark作业的运行速度是非常慢的。
参数调优建议:
每个Spark作业的运行一般设置50~100个左右的Executor进程比较合适,设置太少或太多的Executor进程都不好。设置的太少,无法充分利用集群资源;设置的太多的话,大部分队列可能无法给予充分的资源。
2.executor-memory
参数说明:
该参数用于设置每个Executor进程的内存。Executor内存的大小,很多时候直接决定了Spark作业的性能,而且跟常见的JVM OOM异常,也有直接的关联。
参数调优建议:
每个Executor进程的内存设置4G8G较为合适。但是这只是一个参考值,具体的设置还是得根据不同部门的资源队列来定。可以看看自己团队的资源队列的最大内存限制是多少,num-executors乘以executor-memory,就代表了你的Spark作业申请到的总内存量(也就是所有Executor进程的内存总和),这个量是不能超过队列的最大内存量的。此外,如果你是跟团队里其他人共享这个资源队列,那么申请的总内存量最好不要超过资源队列最大总内存的1/31/2,避免你自己的Spark作业占用了队列所有的资源,导致别的同学的作业无法运行。
3.executor-cores
参数说明:
该参数用于设置每个Executor进程的CPU core数量。这个参数决定了每个Executor进程并行执行task线程的能力。因为每个CPU core同一时间只能执行一个task线程,因此每个Executor进程的CPU core数量越多,越能够快速地执行完分配给自己的所有task线程。
参数调优建议:
Executor的CPU core数量设置为2~4个较为合适。同样得根据不同部门的资源队列来定,可以看看自己的资源队列的最大CPU core限制是多少,再依据设置的Executor数量,来决定每个Executor进程可以分配到几个CPU core。同样建议,如果是跟他人共享这个队列,那么num-executors * executor-cores不要超过队列总CPU core的1/3~1/2左右比较合适,也是避免影响其他同学的作业运行。
计算流程
SparkContext连接到Master,向Master注册并申请资源(CPU Core 和Memory)
Master根据SparkContext的资源申请要求和Worker心跳周期内报告的信息决定在哪个Worker上分配资源,然后在该Worker上获取资源,然后启动StandaloneExecutorBackend;
StandaloneExecutorBackend向SparkContext注册;
SparkContext将Applicaiton代码发送给StandaloneExecutorBackend;并且SparkContext解析Applicaiton代码,构建DAG图,并提交给DAG Scheduler分解成Stage(当碰到Action操作时,就会催生Job;每个Job中含有1个或多个Stage,Stage一般在获取外部数据和shuffle之前产生),然后以Stage(或者称为TaskSet)提交给Task Scheduler,Task Scheduler负责将Task分配到相应的Worker,最后提交给StandaloneExecutorBackend执行;
StandaloneExecutorBackend会建立Executor线程池,开始执行Task,并向SparkContext报告,直至Task完成
所有Task完成后,SparkContext向Master注销,释放资源
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-YWqiUi4k-1589641287391)(D:\临时文件\大数据\Day25-Spark\assets\20180627143538839.png)]
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-5q72AtV3-1589641287393)(D:\临时文件\大数据\Day25-Spark\assets\1565594400497.png)]