1.1避免建立重复RDD数组
一般指,在开发spark做业中,首先基于某个数据源,(如hive或hdfs文件)建立一个初始RDD,接着对这个RDD进行某个算子操做,而后获得下一个RDD,以此类推,循环往复,直到计算出咱们须要的结果;在此过程当中多个RDD会经过不一样算子操做串起来。这个RDD串 `RDD lineage` 也就是RDD的血缘关系链。缓存
**在咱们开发中注意,对于同一份数据,只建立一个RDD,不能建立多个RDD来表明同一份据。网络
1.2尽量复用同一个RDDjvm
1.咱们除了在开发中避免对同一份彻底相同数据建立多个RDD以外,与此同时在数据执行算子还要尽量复用一个RDD;性能
2.好比有一个RDD数据格式为k-v类型,另外一个是单v类型,这两个RDD的value数据彻底同样,那么此时咱们能够只使用k-v类型的那个RDD,由于其中已经包含了另外一个的数据,对于相似这种多个RDD有重叠或包含的状况,咱们尽可能复用一个RDD,这样能够减小算子执行次数,也能够减小RDD的数量。 优化
1.3对于屡次使用RDD进行持久化spa
1.3.1概述对象
1.当咱们在spark代码中屡次对一个RDD作算子操做后,就实现了spark做业的第一步优化,也便是尽量复用RDD,此时就该在这个基础之上进行第二步优化,blog
也就是保证对一个RDD进行执行屡次算子操做时,这个RDD自己仅仅被计算一次。内存
2.spark中对于一个RDD执行屡次算子的默认原理是这样,每次你对一个RDD执行一个算子操做时,都会从新从源头计算一遍,计算出那个RDD来而后进行对这个RDD执行你的算子操做,这种方式性能不好的。
3.所以对于这种状况,咱们建议是对屡次使用RDD进行持久化,此时spark会根据你的持久化策略,将RDD中数据保存到内存或磁盘中,之后每次对这个RDD进行算子操做时,都会直接从内存或磁盘中提取持久化的RDD数据,而后执行算子,而不会从源头从新计算一遍这个RDD,再执行算子操做。
1.3.2持久化策略
1.3.3选择合适的持久化策略
1.默认状况下,性能最高固然是MEMORY_ONLY,可是前提是你的内存足够大,能够绰绰有余存放整个RDD的全部数据由于不进行序列化和反序列化操做就避免了这部分的性能开销;对这个RDD的后续算子操做都是基于内存的数据操做,不须要从磁盘文件中读取数据,性能也很高,并且不须要复制一份数据副本,并远程传送到其余节点上。可是这里必需要注意的是实际的生产环境恐怕可以直接用这种策略场景有限,若是RDD中数据比较多时,直接用这种持久化级别,会致使jvmdeOOM内存溢出异常。
2.若是使用MEMORY_ONLI级别时发生内存溢出,那么建议尝试使用MEMORY_ONLY_SER级别,该级别会将RDD数据序列化后再保存内存中,此时每一个partition仅仅是一个字节数组而已,大大减小对象数量,并下降内存占用,这种级别比MEMORY_ONLY多出来性能开销,主要就是序列化和反序列化的开销,但后续算子能够基于纯内存进行操做,所以性能整体来讲仍是比较高的,此外可能发生的问题同上,若是RDD中数量过多的话,仍是可能致使OOM异常。
3.若是纯内存级别都没法使用,而不MEMORY_AND_DISK策略,由于既然到了这一步就是说明RDD数据量大,内存没法彻底放下,序列化后的数据比较少,能够节省内存和磁盘空间开销,同时该策略会优先尽可能数据比较少,能够节省内存和磁盘空间开销,同时该策略会优先尽可能尝试将数据缓存内存中,内存缓存不下会写入磁盘。
4.一般不建议使用DISK_ONLY和后缀为2的级别,由于彻底基于磁盘文件进行数据读写,会致使性能急剧下降,有时还不如从新计算一次全部RDD,后缀为2级别,必须将全部数据都复制一份副本,而且发送到其它节点上,数据复制以及网络传输会致使较大性能开销,除非要求做业高可用性,不然不建议使用。
1.3.4 gc回收过程