关于Spark性能调优的一些观点

spark是一个基于内存的计算框架。它集成了离线批处理,sql类处理,实时处理/流式计算、机器学习和图计算计算模式。所以spark程序的优化对于spark执行效率来说是非常的重要的。

1、1 开发调优

开发调优首先需要了解一些spark开发的基本设计原则:(1)RDD lineage 设计;(2)算子的合理使用;(3)特殊的操作使用;在实际开发中需要结合自己的业务,来合理、灵活的开发程序;

1、2 原则一:避免创建重复的RDD

通常开发过程中,最初都是基于某一个数据源(HDFS、S3、Hive表)等创建一个初始RDD,然后对这个RDD执行一系列算子操作,直到最终得到我们需要的结果。在执行过程中RDD算子之间链接起来形成了RDD的lineage。
在这里,我们需要注意:对于同一份数据只创建一个RDD。
举个例子吧:
val rdd1 = sc.textFile(“hdfs://172.16.0.33:9000/data/hello.txt”)
val rdd2 = rdd1.map(x => x.split(” “))
…..
val rdd3 = sc.textFile(“hdfs://172.16.0.33:9000/data/hello.txt”)
val rdd4 = rdd3.take(3)
在上面的例子中对于同一份数据创建了多个RDD,这就意味着要消耗资源。所以不是最佳的选择。

1、3 原则二: 尽可能复用同一个RDD

在对于不同数据执行不同的算子操作,尽可能复用RDD, 比如一个RDD[key, value]的数据和另个RDD[key]相同的话,就应该利用前面的RDD进行相关的转化操作,做到尽最大的可能减少算子,提高程序的效率。

1、4 原则三:对于多次使用的RDD进行缓存

我们在程序中做到了对于一个RDD执行多次的算子操作。其实这个RDD仅仅是被计算了一次。。Spark中对于一个RDD执行多次算子的默认原理:每次你对一个RDD执行一个算子操作时,都会重新从源头处计算一遍,计算出那个RDD来,然后再对这个RDD执行你的算子操作。这种方式的性能是很差的。所以我们可以选择把这个RDD进行缓存。rdd1.persist() 或者 rdd1.cache()。关于这俩种缓存的区别:请看下面来自官网(http://spark.apache.org/docs/latest/rdd-programming-guide.html#rdd-persistence)的翻译:
RDD持久化:在内存中持久化(或缓存)数据集是Spark最重要的功能之一。当您需要持久化一个RDD时,每个节点将在内存中存储RDD的分区数据,在内存中进行计算,并在该数据集(或从该数据集中派生的数据集)的其他操作中重用它们。这允许以后的执行动作将更快速(通常超过10x)。缓存是迭代算法和快速交互使用的关键手段。
您可以使用persist()或cache()方法将一个RDD标记为持久化。第一次在action中计算时,它将保存在节点的内存中。Spark的缓存是容错的——如果一个RDD的任何分区数据丢失,它将使用最初创建它的RDD的transformation自动重新计算。
此外,每个持久的RDD都可以使用不同的存储级别进行存储,例如,允许您将数据集持久化到磁盘上,并将其持久化到内存中,但是作为序列化的Java对象(为了节省空间),可以跨节点复制数据集。通过将StorageLevel对象(Scala、Java、Python)传递给persist()来设置这些级别。cache()方法是使用默认存储级别(StorageLevel)的简写。MEMORY_ONLY(在内存中存储反序列化对象)。
![这里写图片描述](https://img-blog.csdn.net/20180718141520355?watermark/2/text/aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3RyeWxs/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70)

猜你喜欢

转载自blog.csdn.net/tryll/article/details/81097275