[Spark] 如何设置Spark资源

转自 1.公众号[Spark学习技巧] 如何设置Spark资源
2.Spark性能优化篇一:资源调优

Spark和YARN管理的两个主要资源:CPU和内存

应用程序中每个Spark Executor都具有相同的固定数量的核心和相同的固定堆大小。

使用--executor-cores命令行参数或者通过设置spark.executor.cores属性指定核心数;
使用--executor-memory命令行参数或者通过设置spark.executor.memory属性配置堆大小。

cores属性控制执行程序可以运行的并发任务数。例如,为每个执行程序设置--executor-cores 5,同时运行最多五个任务。 memory属性控制Spark可以缓存的数据量,以及用于分组,聚合和join的shuffle数据结构的内存的最大大小。


在集群部署模式下,Spark申请资源应该考虑到适应YARN可用的资源,相关的YARN属性是:
yarn.nodemanager.resource.memory-mb控制每个主机上container使用的最大内存总和。
yarn.nodemanager.resource.cpu-vcores控制每个主机上container使用的最大内核总数。


调整Spark executor的内存大小,请记住以下几点:
<1> ApplicationMaster是可以在yarn上申请container,但是自身不会运行executor,它需要占用内存和CPU。在客户端部署模式下,它们默认是1024M和1个core;在集群部署模式下,ApplicationMaster运行驱动程序,因此可以考虑使用--driver-memory和--driver-cores配置资源。

<2> 运行具有太多内存的executor通常会导致过多的垃圾收集延迟。对于单个执行程序,请使用64GB作为上限。

<3> HDFS客户端难以处理许多并发线程。每个executor最多有五个任务可以实现完全写入吞吐量,因此请将每个执行程序的核心数保持在该数量之下。因此--executor-cores不能高于5

<4> 运行微型executor(例如,使用单个核心和运行单个任务所需的足够内存)会抵消在单个JVM中运行多个任务的好处。例如,广播变量必须在每个执行程序上复制一次,因此许多小执行程序会导致更多的数据副本。


资源调优示例:
假设一个集群有六台机器运行nodemanager,每个主机配备16个内核和64 GB内存。
NodeManager容量yarn.nodemanager.resource.memory-mb和yarn.nodemanager.resource.cpu-vcores应分别设置为63 * 1024 = 64512(兆字节)和15。避免将100%的资源分配给YARN容器,因为主机需要一些资源来运行操作系统和Hadoop守护程序。在这种情况下,为这些系统进程留下1GB和一个core,对于有hbase共存的需要预留更多的内存和cpu。

可以考虑使用--num-executors 6 --executor-cores 15 --executor-memory 63G。但是,这种方法不行的:
1、63 GB加上executor内存开销超出了NodeManagers的63 GB容量。
2、ApplicationMaster在其中一个主机上占用一个核心,因此该主机上没有15核执行器的空间。
3、每个执行程序15个核心可能导致较差的HDFS I / O吞吐量。

相反,使用--num-executors 17 --executor-cores 5 --executor-memory 19G:
1、这导致所有主机上有三个executor,除了具有两个executor的ApplicationMaster。
2、--executor-memory计算为(63/3 executor /每台主机):
21 * 0.07 = 1.47GB。 21 - 1.47~19GB。

总结:一般来说资源分配,首先看yarn.nodemanager.resource.memory-mb和yarn.nodemanager.resource.cpu-vcores
(1) 首先确定executor-cores,一般来说不能超过5
(2) num-executors就是:(yarn.nodemanager.resource.cpu-vcores/executor-cores)*机器数-1台ApplicationMaster所占的执行程序个数
(3) driver-memory不需要设置的很大

另外还有一些参数:
spark.default.parallelism:如果不设置这个参数,就会导致Spark自己根据底层HDFS的block数量来设置task的数量,默认是一个HDFS block对应一个task。通常来说,Spark默认设置的数量是偏少的(比如就几十个task),如果task数量偏少的话,就会导致你前面设置好的Executor的参数都前功尽弃。

因此Spark官网建议的设置原则是,设置该参数为num-executors * executor-cores的2~3倍较为合适,比如Executor的总CPU core数量为300个,那么设置1000个task是可以的,此时可以充分地利用Spark集群的资源。

你可能感兴趣的:([Spark] 如何设置Spark资源)