spark调优

 

基本概念和原则

首先,要搞清楚Spark的几个基本概念和原则,否则系统的性能调优无从谈起:

  • 每一台host上面可以并行N个worker,每一个worker下面可以并行M个executor,task们会被分配到executor上面去执行。Stage指的是一组并行运行的task,stage内部是不能出现shuffle的,因为shuffle的就像篱笆一样阻止了并行task的运行,遇到shuffle就意味着到了stage的边界。
  • CPU的core数量,每个executor可以占用一个或多个core,可以通过观察CPU的使用率变化来了解计算资源的使用情况,例如,很常见的一种浪费是一个executor占用了多个core,但是总的CPU使用率却不高(因为一个executor并不总能充分利用多核的能力),这个时候可以考虑让么个executor占用更少的core,同时worker下面增加更多的executor,或者一台host上面增加更多的worker来增加并行执行的executor的数量,从而增加CPU利用率。但是增加executor的时候需要考虑好内存消耗,因为一台机器的内存分配给越多的executor,每个executor的内存就越小,以致出现过多的数据spill over甚至out of memory的情况。
  • partition和parallelism,partition指的就是数据分片的数量,每一次task只能处理一个partition的数据,这个值太小了会导致每片数据量太大,导致内存压力,或者诸多executor的计算能力无法利用充分;但是如果太大了则会导致分片太多,执行效率降低。在执行action类型操作的时候(比如各种reduce操作),partition的数量会选择parent RDD中最大的那一个。而parallelism则指的是在RDD进行reduce类操作的时候,默认返回数据的paritition数量(而在进行map类操作的时候,partition数量通常取自parent RDD中较大的一个,而且也不会涉及shuffle,因此这个parallelism的参数没有影响)。所以说,这两个概念密切相关,都是涉及到数据分片的,作用方式其实是统一的。通过spark.default.parallelism可以设置默认的分片数量,而很多RDD的操作都可以指定一个partition参数来显式控制具体的分片数量。
  • 上面这两条原理上看起来很简单,但是却非常重要,根据硬件和任务的情况选择不同的取值。想要取一个放之四海而皆准的配置是不现实的。看这样几个例子:(1)实践中跑的EMR Spark job,有的特别慢,查看CPU利用率很低,我们就尝试减少每个executor占用CPU core的数量,增加并行的executor数量,同时配合增加分片,整体上增加了CPU的利用率,加快数据处理速度。(2)发现某job很容易发生内存溢出,我们就增大分片数量,从而减少了每片数据的规模,同时还减少并行的executor数量,这样相同的内存资源分配给数量更少的executor,相当于增加了每个task的内存分配,这样运行速度可能慢了些,但是总比OOM强。(3)数据量特别少,有大量的小文件生成,就减少文件分片,没必要创建那么多task,这种情况,如果只是最原始的input比较小,一般都能被注意到;但是,如果是在运算过程中,比如应用某个reduceBy或者某个filter以后,数据大量减少,这种低效情况就很少被留意到。
  • 最后再补充一点,随着参数和配置的变化,性能的瓶颈是变化的,在分析问题的时候不要忘记。例如在每台机器上部署的executor数量增加的时候,性能一开始是增加的,同时也观察到CPU的平均使用率在增加;但是随着单台机器上的executor越来越多,性能下降了,因为随着executor的数量增加,被分配到每个executor的内存数量减小,在内存里直接操作的越来越少,spill over到磁盘上的数据越来越多,自然性能就变差了。

 

spark性能调优有很多措施,下面说说我用到的一些调优手段。

1.RDD分片数和executor个数的协调

要想充分的使数据并行执行,并且能充分的利用每一个executor,则在rdd的个数与executor的个数之间要有一个合适的值。若rdd的个数较多而executor的个数较少,则会导致部分rdd需要等待空闲的executor,这样不能使所有数据同时并行执行。若rdd较少,而executor的个数较多,则会导致部分ecexutor空闲,浪费资源。所以最理想的状态是rdd的个数与executor的个数一致,这样可以达到完全并行,但每个executor的执行能力又是不一样的,有的执行的快,则先执行完的会出现等待的情况,所以应该根据内存的大小来分配executor的个数,一般是取rdd个数不小于executor的数量。

rdd分片数可在程序中设置,一般是textFile()函数的第二个参数。executor的个数通过命令:--num-executors args来设置。

 

2. 优化数据结构

 

Spark 默认使用Java序列化对象,虽然Java对象的访问速度更快,但其占用的空间通常比其内部的属性数据大2-5倍。为了减少内存的使用,减少Java序列化后的额外开销,下面列举一些Spark官网(http://spark.apache.org/docs/latest/tuning.html#tuning-data-structures)提供的方法。

 

(1)使用对象数组以及原始类型(primitive type)数组以替代Java或者Scala集合类(collection class)。fastutil 库为原始数据类型提供了非常方便的集合类,且兼容Java标准类库。

 

(2)尽可能地避免采用含有指针的嵌套数据结构来保存小对象。

 

(3)考虑采用数字ID或者枚举类型以便替代String类型的主键。

 

(4)如果内存少于32GB,设置JVM参数-XX:+UseCom­pressedOops以便将8字节指针修改成4字节。与此同时,在Java 7或者更高版本,设置JVM参数-XX:+UseC­­­­­ompressedStrings以便采用8比特来编码每一个ASCII字符。

 

3.广播变量(broadcast)

当task中需要访问一个Driver端较大的数据时,可以通过使用SparkContext的广播变量来减小每一个任务的大小以及在集群中启动作业的消耗。参考官方文档http://spark.apache.org/docs/latest/tuning.html#broadcasting-large-variables。

4.集群并行度

在Spark集群环境下,只有足够高的并行度才能使系统资源得到充分的利用,可以通过修改spark-env.sh来调整Executor的数量和使用资源,Standalone和YARN方式资源的调度管理是不同的。

 

在Standalone模式下:

 

1. 每个节点使用的最大内存数:SPARK_WORKER_INSTANCES*SPARK_WORKER_MEMORY;

 

2. 每个节点的最大并发task数:SPARK_WORKER_INSTANCES*SPARK_WORKER_CORES。

 

在YARN模式下:

 

1. 集群task并行度:SPARK_ EXECUTOR_INSTANCES* SPARK_EXECUTOR_CORES;

 

2. 集群内存总量:(executor个数) * (SPARK_EXECUTOR_MEMORY+ spark.yarn.executor.memoryOverhead)+(SPARK_DRIVER_MEMORY+spark.yarn.driver.memoryOverhead)。

 

重点强调:Spark对Executor和Driver额外添加堆内存大小,Executor端:由spark.yarn.executor.memoryOverhead设置,默认值executorMemory * 0.07与384的最大值。Driver端:由spark.yarn.driver.memoryOverhead设置,默认值driverMemory * 0.07与384的最大值。

 

通过调整上述参数,可以提高集群并行度,让系统同时执行的任务更多,那么对于相同的任务,并行度高了,可以减少轮询次数。举例说明:如果一个stage有100task,并行度为50,那么执行完这次任务,需要轮询两次才能完成,如果并行度为100,那么一次就可以了。

 

但是在资源相同的情况,并行度高了,相应的Executor内存就会减少,所以需要根据实际实况协调内存和core。此外,Spark能够非常有效的支持短时间任务(例如:200ms),因为会对所有的任务复用JVM,这样能减小任务启动的消耗,Standalone模式下,core可以允许1-2倍于物理core的数量进行超配。

 

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值