Spark性能调优兹以为可分为三大块:
- JVM层面的调优
- 程序层面的调优
- 业务和平台层面的调优
本篇主要描述程序层面的调优。主要包括三方面:
1,数据序列化
序列化对提高分布式程序的性能起到非常重要的作用。一个不好的序列化方式(如序列化模式的速度非常慢或者序列化结果非常大)会极大降低计算速度。在很多情况下这是我们优化Spark应用的第一选择。Spark试图在方便和性能之间获得一个平衡。Spark提供了两个序列化类库。
- java序列化(默认):Java序列化非常灵活,但是速度较慢,在某些情况下序列化的结果也比较大。
- Kyro序列化:速度快,产生的结果也比较紧凑。缺点是不支持所有类型,需要提前注册程序中所有的类。
如果需要使用Kryo序列化。要经过连个步骤:(1)申明使用kryo序列化(2)注册序列化类
val conf = new SparkConf
conf.set("spark.serializer", "org.apache.spark.serializer.KryoSerializer")
spark-submit --conf spark.serializer=org.apache.spark.serializer.KryoSerializer
public class User implements KryoRegistrator
val conf = new SparkConf
conf.set("spark.serializer", "org.apache.spark.serializer.KryoSerializer")
.registerKryoClasses(Array(classOf[com.spark.test.offline.udf.User]))
2,内存优化
Spark内存优化
3,其他优化
Spark程序优化最主要的是数据序列化和内存优化,对于大多数程序而言,采用Kryo序列化能够解决性能有关的大部分问题。除此之外还有其他的一些序列化方式。
3.1 并行度
除非为每一个操作都设置足够高的并行度,否则集群不能有效地被利用。Spark会根据每一个文件的大小自动设置map task的个数(我们也可以通过SparkContext的配置参数来控制);对于分布式reduce任务(例如groupByKey或者reduceByKey),则利用最大RDD的分区数,我们可以通过配置reduceByKey这些方法的第二个参数来传入并行度或者通过系统参数spark.default.parallelism来改变默认值。通常来说,我们,在集群中,我们建议为每一个CPU 核分配2-3个任务。
3.2 Reduce Task的内存的使用
有时候我们会碰到OOM的错误,这并不是因为我们的RDD不能加载到内存,而是因为任务执行的数据集过大,例如正在执行groupByKey操作的Reduce任务。最简单的方法是增加并行度,这样每一个任务的输入会变得更小。
3.3 广播“大变量”
使用SparkContext的广播变量可以有效减少每一个任务的大小以及在集群中启动作业的消耗。
|