1.分配更多资源:分配executor、cpu per executor、memory per executor、driver memory资源。在我们在生产环境中,提交spark作业时,用的spark-submit shell脚本,里面调整对应的参数。你能使用的资源有多大,就尽量去调节到最大的大小(executor的数量,几十个到上百个不等;executor内存;executor cpu core)。
2.合理设置并行度:就可以完全充分利用你的集群计算资源,并且减少每个task要处理的数据量,最终,就是提升你的整个Spark作业的性能和运行速度。官方是推荐,task数量,设置成spark application总cpu core数量的2~3倍,比如150个cpu core,基本要设置task数量为300~500。如何设置一个Spark Application的并行度?SparkConf conf = new SparkConf()
.set("spark.default.parallelism", "500")。
3.重构RDD架构以及RDD持久化:RDD架构重构与优化。公共RDD一定要实现持久化。持久化,是可以进行序列化的。为了数据的高可靠性,而且内存充足,可以使用双副本机制,进行持久化。
4.广播大变量:广播变量的好处,不是每个task一份变量副本,而是变成每个节点的executor才一份副本。这样的话,就可以让变量产生的副本大大减少。sc.broadcast(变量)。
5.使用Kryo序列化:当使用了序列化的持久化级别时,在将每个RDD partition序列化成一个大的字节数组时,就会使用Kryo进一步优化序列化的效率和性能。
第一步,在SparkConf中设置一个属性,SparkConf.set("spark.serializer", "org.apache.spark.serializer.KryoSerializer")。
第二步,注册你使用到的,需要通过Kryo序列化的,一些自定义类,SparkConf.registerKryoClasses()。
6.使用fastutil优化数据格式:如果外部变量是某种比较大的集合,那么可以考虑使用fastutil改写外部变量,首先从源头上就减少内存的占用,通过广播变量进一步减少内存占用,再通过Kryo序列化类库进一步减少内存占用。
7.调节数据本地化等待时长:new SparkConf().set("spark.locality.wait", "10")。