Spark编程技巧

2022-09-29 17:29:55 浏览数 (1)

Spark是一种强烈依赖内存的计算框架,结合其运行流程,可以有很多可以调优的地方

用reduceByKey 替代groupByKey

这两个转换都有shuffle过程发生,且都类似map reduce,但是reduceByKey会在map阶段会对相同的key进行聚合,极大的减少了map产生的数据量,进而减少了shuffle的数据量,提高了程序的执行效率

避免shuffle

shuffle类算子会将多个节点的key,拉取到一个节点上,进行join或者聚合操作,代价很大。

关于缓存

如果一个rdd被多个rdd依赖,就要持久化该rdd,避免被生成多次,而持久化时又有一些小技巧,如下

用persist(MEMORY_ONLY_SER) 代替persist和cache

persist的默认持久化类型是MEMORY_ONLY,该类型在内存中会缓存原始的对象,而MEMORY_ONLY_SER将对象序列化后再缓存,这样会节省大量的内存。因为Spark模型的各个阶段都会耗内存,而且现在计算的瓶颈一般不在CPU而在IO上,节省了内存。会让Spark其他阶段拥有更多的内存,从而减少了和磁盘的交互,进而加快作业的执行速度

内存不够时

内存不够时,使用 MEMORY_AND_DISK_SER

避免使用DISK_ONLY和后缀为_2的持久化方式

DISK_ONLY将rdd缓存在磁盘上,基于磁盘的读写会严重影响性能 后缀为_2的持久化方式,会将rdd复制一份副本,发送到其他节点上,数据复制和网络传输的性能开销较大

使用Kryo序列化

该种序列化方式会比默认的java序列化方式节省2到5倍的空间

分解一个job之中的transformation

尽量避免在一个transformation中处理所有的逻辑, 尽量分解成map, filter等之类的操作,这样程序会更容易理解

调低spark.memory.fraction

如果因为GC导致outofmemory,很可能是老年代的内存较小,可以调低该参数

包冲突

  1. 将spark自带的包设置成provided,这样就可以使用spark内核自带的相应类
  2. spark自带了很多包,比如org.json4s, guava等,因为这些包升级时没做向前兼容性,如果用户自己引入了这些包,很可能产生运行时异常。这个时候,有两种方式处理:不使用这些包,这样就将雷跳过去了;使用shade打包,改变包的名字,也可以将雷跳过去

yarn-client

选择了yarn-client模式, 因此是默认没有开启本地Driver的gc log的, 为了更好应对出错时debug, 建议在本地export 因此是默认没有开启本地 Driver 的 gc log 的, 为了更好应对出错时 debug, 建议在本地 export

代码语言:javascript复制
SPARK_SUBMIT_OPTS=" -Xloggc:tmp/gc_log  -XX: PrintGCApplicationStoppedTime  -XX: PrintGCDetails  -XX: PrintGCDateStamps  -verbose:gc  -XX: UseGCLogFileRotation  -XX:NumberOfGCLogFiles=10  -XX:GCLogFileSize=10M " 
  • 查看调试信息
代码语言:javascript复制
spark-submit --verbose 

参考

Spark性能优化指南——基础篇 Spark性能优化指南——高级篇 Spark Tuning

0 人点赞