一、参数篇
1、Spark SQL 参数
hive.exec.orc.split.strategy
默认值: HYBRID
参数说明:orc 文件切片策略。rdd action生成Task时会计算
调优建议:当我们执行SQL处理ORC格式的HIVE表时,会发现很简单的一个处理会花很长时间去生成task 。原因是用Spark读取ORC文件时,Spark会使用ETL模式读取ORC文件,这时会扫每个ORC文件上的index。扫完之后才会开始进行真正的 Spark Orc 切片缓慢优化。 当将策略修改成BI之后,将直接以ORC文件个数划分TASK。加快切分task的速度。但这么搞会带来执行上变慢,请根据自己的需要设置

2、shuffle相关参数调优

以下是Shffule过程中的一些主要参数,这里详细讲解了各个参数的功能、默认值以及基于实践经验给出的调优建议。

spark.shuffle.file.buffer

  • 默认值:32k
  • 参数说明:用于设置shuffle write task的BufferedOutputStream的buffer缓冲大小。将数据写到磁盘文件之前,会先写入buffer缓冲中,待缓冲写满之后,才会溢写到磁盘。
  • 调优建议:如果作业可用的内存资源较为充足的话,可以适当增加这个参数的大小(比如64k),从而减少shuffle write过程中溢写磁盘文件的次数,也就可以减少磁盘IO次数,进而提升性能。在实践中发现,合理调节该参数,性能会有1%~5%的提升。

spark.reducer.maxSizeInFlight

  • 默认值:48m
  • 参数说明:该参数用于设置shuffle read task的buffer缓冲大小,而这个buffer缓冲决定了每次能够拉取多少数据。
  • 调优建议:如果作业可用的内存资源较为充足的话,可以适当增加这个参数的大小(比如96m),从而减少拉取数据的次数,也就可以减少网络传输的次数,进而提升性能。在实践中发现,合理调节该参数,性能会有1%~5%的提升。

spark.shuffle.io.maxRetries

  • 默认值:3
  • 参数说明:shuffle read task从shuffle write task所在节点拉取属于自己的数据时,如果因为网络异常导致拉取失败,是会自动进行重试的。该参数就代表了可以重试的最大次数。如果在指定次数之内拉取还是没有成功,就可能会导致作业执行失败。
  • 调优建议:对于那些包含了特别耗时的shuffle操作的作业,建议增加重试最大次数(比如60次),以避免由于JVM的full gc或者网络不稳定等因素导致的数据拉取失败。在实践中发现,对于针对超大数据量(数十亿~上百亿)的shuffle过程,调节该参数可以大幅度提升稳定性。

spark.shuffle.io.retryWait

  • 默认值:5s
  • 参数说明:具体解释同上,该参数代表了每次重试拉取数据的等待间隔,默认是5s。
  • 调优建议:建议加大间隔时长(比如60s),以增加shuffle操作的稳定性。

spark.shuffle.memoryFraction

  • 默认值:0.2
  • 参数说明:该参数代表了Executor内存中,分配给shuffle read task进行聚合操作的内存比例,默认是20%。
  • 调优建议:在资源参数调优中讲解过这个参数。如果内存充足,而且很少使用持久化操作,建议调高这个比例,给shuffle read的聚合操作更多内存,以避免由于内存不足导致聚合过程中频繁读写磁盘。在实践中发现,合理调节该参数可以将性能提升10%左右。

spark.shuffle.manager

  • 默认值:sort
  • 参数说明:该参数用于设置ShuffleManager的类型。Spark 1.5以后,有三个可选项:hash、sort和tungsten-sort。HashShuffleManager是Spark 1.2以前的默认选项,但是Spark 1.2以及之后的版本默认都是SortShuffleManager了。tungsten-sort与sort类似,但是使用了tungsten计划中的堆外内存管理机制,内存使用效率更高。
  • 调优建议:由于SortShuffleManager默认会对数据进行排序,因此如果你的业务逻辑中需要该排序机制的话,则使用默认的SortShuffleManager就可以;而如果你的业务逻辑不需要对数据进行排序,那么建议参考后面的几个参数调优,通过bypass机制或优化的HashShuffleManager来避免排序操作,同时提供较好的磁盘读写性能。这里要注意的是,tungsten-sort要慎用,因为之前发现了一些相应的bug。

spark.shuffle.sort.bypassMergeThreshold

  • 默认值:200
  • 参数说明:当ShuffleManager为SortShuffleManager时,如果shuffle read task的数量小于这个阈值(默认是200),则shuffle write过程中不会进行排序操作,而是直接按照未经优化的HashShuffleManager的方式去写数据,但是最后会将每个task产生的所有临时磁盘文件都合并成一个文件,并会创建单独的索引文件。
  • 调优建议:当你使用SortShuffleManager时,如果的确不需要排序操作,那么建议将这个参数调大一些,大于shuffle read task的数量。那么此时就会自动启用bypass机制,map-side就不会进行排序了,减少了排序的性能开销。但是这种方式下,依然会产生大量的磁盘文件,因此shuffle write性能有待提高。

spark.shuffle.consolidateFiles

  • 默认值:false
  • 参数说明:如果使用HashShuffleManager,该参数有效。如果设置为true,那么就会开启consolidate机制,会大幅度合并shuffle write的输出文件,对于shuffle read task数量特别多的情况下,这种方法可以极大地减少磁盘IO开销,提升性能。
  • 调优建议:如果的确不需要SortShuffleManager的排序机制,那么除了使用bypass机制,还可以尝试将spark.shffle.manager参数手动指定为hash,使用HashShuffleManager,同时开启consolidate机制。在实践中尝试过,发现其性能比开启了bypass机制的SortShuffleManager要高出10%~30%。
二、编程篇
1.coalesce和 repartition 增加分区个数
增加分区个数减少数据太过于集中造成热点问题
2.减少大量小文件
避免作业和key过碎,造成大量的小文件问题
3.数据倾斜
增加key标识设计两路聚合,
三、策略优化
1、Spark Streaming 相关
  1. 关闭Spark Streaming 的Event log 功能
     原因:当运行Spark Streaming 应用时,Event log 就显的不那重要了。每次Spark Streaming 都会攒一些数据处理,让History Server 处理这些数据生成的Event log 无太大意义。同时存储这些Event log 到HDFS也浪费存储
     关闭方法 : spark-submit –conf spark.eventLog.enabled=false
2、Spark History 相关
  1. 增加Spark History Server JVM 优化参数
     原因:目前Spark  History 长期运行后,会造成JVM内存持续变大,最终卡死(2.1.0 之前版本)
     优化方法:在spark-env.sh 增加如下参数
SPARK_HISTORY_OPTS="-Xms48g -Xmn10g -XX:+UseConcMarkSweepGC -XX:CMSInitiatingOccupancyFraction=70 -XX:+UseCMSCompactAtFullCollection -XX:+CMSParallelRemarkEnabled -XX:CMSFullGCsBeforeCompaction=0 -XX:CMSMaxAbortablePrecleanTime=1000 -XX:+CMSClassUnloadingEnabled -XX:MaxTenuringThreshold=10  -Xloggc:/data0/hadoop-logs/gc_sparkhistory_${timestamp}.log  -verbose:gc -XX:+PrintGCDetails -XX:+PrintGCDateStamps -XX:+PrintGCApplicationStoppedTime -XX:+PrintGCApplicationConcurrentTime -XX:+PrintTenuringDistribution -Dcom.sun.management.jmx -Dcom.sun.management.jmxremote.port=8999 -Dcom.sun.management.jmxremote.authenticate=false -Dcom.sun.management.jmxremote.ssl=false $SPARK_HISTORY_OPTS"
  1. 优化Spark History Server参数
spark.eventLog.enabled          true
spark.eventLog.compress         true
spark.history.fs.update.interval  30s
spark.history.retainedApplications  30  //缓存的app信息个数,不要太大。否则很占内存
spark.history.fs.cleaner.enabled  true
spark.history.fs.cleaner.interval  12h
spark.history.fs.cleaner.maxAge  30d    //如果每天的作业量比较大,建议调小些值降低HDFS的存储压力
spark.history.fs.numReplayThreads 16  //建议调大,加速History处理HDFS上event log的处理速度
spark.history.ui.maxApplications 5000  //建议不要过大,否则WebUI首页会很卡。 不在UI界面上的App,可以直接用 host:18080/history/application_1506512832290_0094/1/jobs/  获取历史日志