1.原文链接
https://tech.meituan.com/spark-tuning-basic.html
2.介绍:
在看过美团点评的文章后,我觉得对Spark的调优写的十分棒,我决定综合自己对其的理解写一篇针对这篇文章的代码调优方面的读后感。以加深对其的理解。调优分为基础篇和高级篇,我先对比较倾向于代码的基础篇进行讲解。
3.正文
原则一:避免重复的RDD
RDD的根本就是一个数据集,我们需要从外部数据源或者容器类中获取数据,创建RDD,在编程中我们不应对相同的一份数据进行多次读取,创建多个RDD,这对集群来说是一种资源的浪费。
原则二:尽可能复用同一个RDD
在对不同的数据执行算子操作时还要尽可能地复用一个RDD,例如一个RDD中有key-value,我们需要对value进行操作,不需要新建一个RDD接手value的数据,而是可以使用_.2这个操作,来复用原始的RDD来得到想要的数据。这样做可以尽量减少RDD的数量,也减少了算子操作的数量。
原则三:对多次使用的RDD进行持久化
这个十分简单,就是对多次使用的RDD进行一个持久化的操作(persist()),这么做的好处是减少对RDD的重复计算,提高效率。Spark对于执行多算子默认原理为,每次你对一个RDD执行一个算子操作时,都会重新从源头处计算一遍,计算出那个RDD来,然后再对这个RDD执行你的算子操作。这种方式的性能是很差的。我们可以保留一个中间状态,使得RDD不必做一些重复而无用的操作。例如:
//这段代码中reduce算子操作会重新读取数据。
val rdd1 = sc.textFile("hdfs://192.168.0.1:9000/hello.txt")
rdd1.map(...)
rdd1.reduce(...)
//避免这种问题可以对rdd1进行两种方式的处理
1.使用cache()
val rdd1 = sc.textFile("hdfs://192.168.0.1:9000/hello.txt").cache()
2.使用persist()方法
val rdd1 = sc.textFile("hdfs://192.168.0.1:9000/hello.txt").persist(StorageLevel.MEMORY_AND_DISK_SER)
总结:这两种方式的关系可以在源码中发现,cache()方法就是persist(StorageLevel.MEMORY_ONLY),这样就可以了解有关持久化这两个方法的作用与关系
def persist(newLevel: StorageLevel): this.type = {
if (isLocallyCheckpointed) {
// This means the user previously called localCheckpoint(), which should have already
// marked this RDD for persisting. Here we should override the old storage level with
// one that is explicitly requested by the user (after adapting it to use disk).
persist(LocalRDDCheckpointData.transformStorageLevel(newLevel), allowOve