Spark作业不知道该如何分配资源怎么办?

前几天有好几个朋友问我关于spark作业分配资源的问题:即在提交作业的时候,不知道该分配多少资源比较好?我的回答是靠经验,仔细想想靠经验这等于不是没说吗,总有一些方法论或者思路的吧。所以就有了这篇文章,下笔的时候着实是不知道该怎么写,所以在网上搜索了一下,看看大佬们是怎么回答的。赶巧了不是,还真发现3年前就有人问过这个问题。

图片

看了下评论,我感觉我能看懂,但不知道朋友们是否能看懂,所以我想还是要再详细啰嗦一下吧

图片

首先呢,spark官网给我们提供了一些硬件层面的建议,先上链接https://spark.apache.org/docs/latest/hardware-provisioning.html。

但是这个文章并没有很细粒度介绍应用级别该如何分配资源。不过涉及到的几个方向可以参考一下,比如内存,CPU

首先来复习一下spark涉及到这两块部分参数如下:

--num-executors/(SparkSQL中是spark.executor.instances 参数)

该参数代表了作业使用的总共executor个数

--driver-memory/(SparkSQL配置的是spark.driver.memory参数)

该参数代表了Driver端所消耗的内存,通常Driver端不会消耗太多资源,所以不需要给太多资源。

--executor-memory(SparkSQL配置的是spark.executor.memory参数)

该参数代表了每个executor所占用的内存

--executor-cores/(SparkSQL配置的是spark.executor.cores参数)

该参数代表了一个executor中能够并行执行的task数(注意并行和并发的区别!)

通常一个Spark作业所消耗的总内存数>=(spark.executor.instances)*(spark.exector.memory);

所占用的CPU个数>=(spark.executor.instances)*(spark.exector.cores)。

这里之所以要用大于,是因为AppMaster也要占用资源的!扯到AppMaster,那需要再复习一下Yarn部分的两个参数:

yarn.nodemanager.resource.memory-mb

该参数表示的是nm可供Yarn使用最大可用内存

yarn.nodemanager.resource.cpu-vcores

该参数表示的是nm可供yarn使用的最大虚拟cpu数量

一般在实际生产环境中,yarn可分配的总资源肯定是已经分配好了的。甚至是会有单独的spark作业队列(这里也要看yarn的调度模式,是fair,还是fifo,还是capacity)。

我们这里先举个例子来说明下:假设我们有一个裸集群,共有6个节点,每个节点都是16c 64g的配置(真实情况下每个节点的配置可能是参差不齐的)。

但是我们不可能把所有的资源全分配到yarn上,还是要留一部分作为系统运转的,那么每个节点留1C 1G 好了,采取极限的方式。最后每个节点可供yarn分配的资源如下:

yarn.nodemanager.resource.memory-mb=63g

yarn.nodemanager.resource.cpu-vcores=15

那么总资源就是all_memory=63*6=378g;all_cpu=6*15=90c

我们假设每个Executor并行度为5,那么就需要90/5=18个executor,但是需要留一个给AppMaster,所以–num-exectors=17;刚才算下来总共需要18个Executor,一共6个节点,平均每个节点是启动3个exector,一个节点是63g,那么每个executor可占用内存就是21g,请注意哦:每个executor并不是把21g全部给作业用,还要留一部分资源用来存储栈,buffer之类的开销以此来保证稳定性,也就是常说的堆外内存,通过spark.executor.memoryOverhead参数来设置这块的开销,其值=max(384mb,0.1*executorMemory)。因此这部分堆外内存=max(384mb,0.1*21)~=2g。那么堆内内存=21-2=19g。

这里用表格来汇总一下:

也就是说在提交作业的时候,其参数配置值不能大于以下值(这里的例子是假设把资源全给你的任务去用!):

--executor-cores / spark.executor.cores = 5--executor-memory / spark.executor.memory = 19--num-executors / spark.executor.instances = 17

节点数

内存/每节点

CPU/每节点

Yarn可分配最大内存数

Yarn可分配最大CPU

假设每个executor并行度数

总executor数

实际干活的executor数

每个节点可启动的executor数

每个executor占用的内存

堆外内存

实际干活所用到的内存

6

64g

16C

63g*6=378g

15C*6=90C

5

90C/5=18

18-1=17

18/6=3

63g/3=21g

max(384mb,0.1*21g)=2g

21g-2g=19g






9

90c/9=10

10-1=9

10/6~=2

63g/~=2~=37g

max(384mb,0.1*37g)=3g

37g-3=34g

可能有朋友会困惑,为什仫每个executor并行度设置为5,当然也可以调大。如果调大每个executor的并行度,也相当于是提高了并行能力,这样的话就减少了task来回轮询的次数,比如你有100个task,每个executor执行20个task,那么要轮询5次;如果每个executor设置50个task,那么要轮询2次;这样一来就会增大每个executor所持有的内存。

其实可以按照前面论坛里提到的一种评估方式就是按照task数量来倒推,官方建议一个cpu core是处理2~3个task。

图片

那么假设有100个task,最多需要50c,还是按照上面的例子,这个时候就要看你是采取每个节点均摊的方式呢,还是某几个节点集中处理。采取何种方式还要结合你实际处理的数据量和计算复杂逻辑(因为这里还要思考网络消耗和本地化计算,每个节点的负载情况等等因素),当然通常情况下是采取均摊的方式,那么每个节点大概会使用8c。那么每个节点启动几个executor呢?是启动一个executor,还是2个executor,每个executor,每个executor大概占用多大内存呢?这个时候就要看你的代码逻辑是计算多一些还是缓存多一些。这里就涉及到内存模型的东西了,不知道内存模型的朋友再复习一下我原来写的文章:Tungsten On Spark-内存模型设计

尽管以上资源分配都已经评估好了,但并不代表后续不需要优化了,不然网上怎么会有那么多优化文章,同时还要注意团队协作资源,不能把所有的资源都给你用,不然别人还怎么干活?

所以还要在你评估的资源上再缩减一部分,这样一来一回可能需要不断的调整,这也是为什仫很多人问到怎么分配资源的时候,都会说一句靠经验!

小编觉得这玩意真的是没有公式可套用的。

如果你有更好的分配资源的方法论或者有哪里写的不对的地方,欢迎大佬联系我分享给其他小伙伴们。

如果你有其他困扰的问题,欢迎骚扰我~

参考:

  • spark官网

  • https://bbs.csdn.net/topics/392153088

猜你喜欢

转载自blog.csdn.net/qq_28680977/article/details/122429880