Spark性能调优
分配更多的资源:
分配哪些资源:
在哪里可以设置这些资源:
在实际的生产环境中,提交spark任务时,使用spark‐submit shell脚本,在里面调整对应的参数。
提交任务的脚本:
参数调节的大小:
第一种情况:Standalone模式
第二种情况:Yarn模式
Spark的并行度:
如何提高并行度:
可以设置task的数量,至少设置成与Spark Application的总CPU core数量相同(最理想情况,150个core,分配150task,一起运行,差不多同一时间运行完毕)如何设置task数量:
给RDD重新设置partition的数量:
提高sparksql运行的task数量:
RDD的重用和持久化:
如何对RDD进行持久化:
1.cache方法默认是把数据持久化到内存中 。例如:rdd.cache ,其本质还是调用了persist方法
RDD持久化的时候可以采用序列化:
1.如果正常将数据持久化在内存中,那么可能会导致内存的占用过大,这样的话,也许会导致OOM内存溢出。
2.当纯内存无法支撑公共RDD数据完全存放的时候,就优先考虑使用序列化的方式在纯内存中存储。将RDD的每个partition的数据,序列化成一个字节数组;序列化后,大大减少内存的空间占用。
3.序列化的方式,唯一的缺点就是,在获取数据的时候需要反序列化。但是可以减少占用的空间和便于网络传输。
4.如果序列化纯内存方式,还是导致OOM内存溢出;就只能考虑磁盘的方式,内存+磁盘的普通方式(无序列化)。
广播变量引入:
广播变量允许将变量只广播(提前广播)给各个Executor。该Executor上的各个task再从所在节点的BlockManager(负责管理某个Executor对应的内存和磁盘上的数据)获取变量,而不是从Driver获取变量,从而提升了效率。
广播变量,初始的时候,就在Drvier上有一份副本。通过在Driver把共享数据转换成广播变量。
task在运行的时候,想要使用广播变量中的数据,此时首先会在自己本地的Executor对应的BlockManager中,尝试获取变量副本;如果本地没有,那么就从Driver远程拉取广播变量副本,并保存在本地的BlockManager中;
此后这个Executor上的task,都会直接使用本地的BlockManager中的副本。那么这个时候所有该Executor中的task都会使用这个广播变量的副本。也就是说一个Executor只需要在第一个task启动时,获得一份广播变量数据,之后的task都从本节点的BlockManager中获取相关数据。
使用后的性能分析:
如何使用广播变量:
1.通过SparkContext的broadcast方法把数据转换成广播变量,类型为Broadcast。
Spark序列化:
Spark在进行任务计算的时候,会涉及到数据跨进程的网络传输、数据的持久化,这个时候就需要对数据进行序列化。
Spark默认采用Java的序列化器。默认java序列化的优缺点如下:
其优点:处理起来方便,不需要我们手动做其他操作,只是在使用一个对象和变量的时候,需要实现Serializble接口。
Kryo序列化:
Kryo序列化启用后生效的地方:
Kryo序列化机制,一旦启用以后,会生效的几个地方:
算子中的外部变量可能与driver需要涉及到网络传输,就需要用到序列化。最终可以优化网络传输的性能,优化集群中内存的占用和消耗。
2.持久化RDD时进行序列化,StorageLevel.MEMORY_ONLY_SER
的占满内存,频繁发生GC。
下游的stage中的task,拉取上游stage中的task产生的结果数据,跨网络传输,需要用到序列化。最终可以优化网络传输的性能。
如何开启Kryo序列化:
2.注册需要通过Kryo序列化的一些自定义类。
fastutil介绍:
fastutil能够提供更小的内存占用,更快的存取速度,我们使用fastutil提供的集合类,来替代自己平时使用的JDK的原生的Map、List、Set。
fastutil的好处:
1.fastutil集合类,可以减小内存的占用,并且在进行集合的遍历、根据索引(或者key)获取元素的值和设置元素的值的时候,提供更快的存取速度;
2.fastutil也提供了64位的array、set和list,以及高性能快速的,实用的IO类,来处理二进制和文本类型的文件;
3.fastutil最新版本要求Java 7以及以上版本;
4.fastutil的每一种集合类型,都实现了对应的Java中的标准接口(比如fastutil的map,实现了Java的Map接口),因此可以直接放入已有系统的任何代码中。
5.fastutil还提供了一些JDK标准类库中没有的额外功能(比如双向迭代器)。
6.fastutil除了对象和原始类型为元素的集合,fastutil也提供引用类型的支持,但是对引用类型是使用等于号(=)进行比较的,而不是equals()方法。
算子函数使用了外部变量:
1.可以使用Broadcast广播变量优化;
2.可以使用Kryo序列化类库,提升序列化性能和效率;
3.如果外部变量是某种比较大的集合,那么可以考虑使用fastutil改写外部变量;
算子函数里使用了比较大的集合:
在你的算子函数里,也就是task要执行的计算逻辑里面,如果有逻辑中,出现要创建比较大的Map、List等集合,
可能会占用较大的内存空间,而且可能涉及到消耗性能的遍历、存取等集合操作;
那么此时,可以考虑将这些集合类型使用fastutil类库重写,使用了fastutil集合类以后,就可以在一定程度上,减少task创建出来的集合类型的内存占用。
fastutil的使用:
第一步:在pom.xml中引用fastutil的包。
第二步:平时使用List(Integer)的替换成IntList即可。
本地化级别:
1.PROCESS_LOCAL:进程本地化。
代码和数据在同一个进程中,也就是在同一个Executor中;计算数据的task由Executor执行,数据在Executor的BlockManager中;性能最好。
2.NODE_LOCAL:节点本地化。
3.RACK_LOCAL:机架本地化。
4.ANY:无限制。
数据本地化等待时长:默认3s。
JVM调优的原因:Java虚拟机内存不足。
以上是关于spark性能调优的内容,若有不对或不全面的地方,欢迎指正和补充。

浙公网安备 33010602011771号