1.代码调优:
- 避免创建重复的RDD
- 复用同一个RDD
- 对多次使用的RDD进行持久化
- 如何选择一种最合适的持久化策略呢?
- 答: cache--MEMORY_ONLY; persist:MEMORY_ONLY,MEMORY_ONLY_SER,MEMORY_AND_DISK_SER
- checkpoint:如果一个RDD的计算时间比较长或者计算起来比较复杂。一般将这个RDD的计算结果保存到HDFS上,这样数据会更加安全。如果一个RDD的依赖关系非常长,也会使用checkpoint,切断依赖关系,提高容错的效率。
- 避免使用shuffle类的算子
- 可以使用广播变量+filter,广播变量+map,广播变量+flatMap 来替换join算子
- 使用map-side预聚合的shuffle类算子:如reduceByKey. aggregateByKey combineByKey
- 尽量使用高性能的算子: 使用reduceByKey 替代 groupByKey 使用mapPartition替代map 使用foreachPartition替代foreach 。filter后使用coalesce减少分区
- 使用 Kryo优化序列化性 Sparkconf.set("spark.serializer","org.apache.spark.serializer.KryoSerializer").registerKryoClasses(new Class[]{SpeedSortKey.class})
- 数据本地化的级别:PROCESS_LOCAL:task计算的数据在本进程(executor)的内存中。NODE_LOCAL:task所计算的数据在本节点所在的磁盘上,或者task所计算的数据在本节点其他executor进行的内存中。NO_PREF:task所计算的:数据在关系型数据库中。RACK_LOCAL:task所计算的数据在同机架的不同节点的磁盘或者executor进进程的内存中。Any:跨机架。
Spark中任务调度时,TaskScheduler在分发之前需要依据数据的位置来分发,最好将task分发到数据所在的节点上,如果TaskScheduler分发的task在默认3s依然无法执行的话,TaskScheduler会重新发送这个task到相同的Executor中去执行,会重试5次,如果依然无法执行,那么TaskScheduler会降低一级数据本地化的级别再次发送task。
如上图中,会先尝试1,PROCESS_LOCAL数据本地化级别,如果重试5次每次等待3s,会默认这个Executor计算资源满了,那么会降低一级数据本地化级别到2,NODE_LOCAL,如果还是重试5次每次等待3s还是失败,那么还是会降低一级数据本地化级别到3,RACK_LOCAL。这样数据就会有网络传输,降低了执行效率。如何提高数据本地化的级别?答:可以增加每次发送task的等待时间(默认都是3s),将3s倍数调大。具体的一些参数名: spark.locality.wait ; spark.locality.wait.process(针对PROCESS_LOCAL级别); spark.locality.wait.node(针对NODE_LOCAL级别); spark.locality.wait.rack(针对RACK_LOCAL级别)
13. spark shuffle调优
buffer大小; shuffle read拉取数据量的大小; shuffle聚合内存的比例; 拉取数据重试的次数;
重试间隔时间; spark shuffle的种类;