Spark性能调优(三)---在实际项目中重构RDD架构以及RDD持久化

一、为什么要重构RDD,持久化RDD

①为什么需要重构RDD

Spark性能调优(三)---在实际项目中重构RDD架构以及RDD持久化

如上图所示, RDD2和RDD3是RDD1执行相同的算子得到的RDD,是相同的RDD。对于这种需要被重复使用,差不多的RDD,可以抽取为一个共同的RDD,供后面的RDD计算时,重复使用。

②为什么持久化RDD

Spark性能调优(三)---在实际项目中重构RDD架构以及RDD持久化

如上图所示,如果没有持久化RDD,那么在获取RDD3和RDD4的时候,都需要从HDFS读取文件,转换成RDD1,然后转换成RDD2,最后再转换成RDD3或RDD4。可以看到,从HDFS读取文件,转换成RDD1,然后转换成RDD2,这一个过程被执行了两边。虽然RDD3和RDD4都是从RDD3转换而来的,但是由于没有对RDD2执行持久化操作,导致每次使用RDD2的时候,父RDD以及父RDD的父RDD等都需要重新执行,造成性能的下降,因此需要进行持久化操作。

 

二、RDD重构和持久化策略

对于要多次使用和计算的RDD,一定要进行持久化。也就是说,将RDD的数据缓存到内存中/磁盘中,(BlockManager),以后无论对这个RDD做多少次计算,直接取持久化之后的数据,比如从内存中或磁盘中直接取数据。

持久化的数据,可以进行序列化。如果将正常的数据持久化在内存中,可能导致内存的占用过大,导致OOM内存溢出。

当纯内存无法支撑公共RDD数据完全存放的时候,就优先考虑,使用序列化的方式在纯内存中存储。将RDD的每个partition数据,序列化成一个大的字节数组,只有一个对象;序列化后,大大减少内存的占用。

持久化的几种策略:

StorageLevel.MEMORY_ONLY(),纯内存,无序列化,那么就可以用cache()方法来替代
StorageLevel.MEMORY_ONLY_SER(),第二选择,纯内存+序列化
StorageLevel.MEMORY_AND_DISK(),第三选择,内存+磁盘
StorageLevel.MEMORY_AND_DISK_SER(),第四选择,内存+磁盘+序列化
StorageLevel.DISK_ONLY(),第五选择,纯磁盘

双副本机制:

StorageLevel.MEMORY_ONLY_2()
StorageLevel.MEMORY_ONLY_SER_2()
StorageLevel.MEMORY_AND_DISK_2()
StorageLevel.MEMORY_AND_DISK_SER_2()
StorageLevel.DISK_ONLY_2()

为了数据的高可靠性,在内存充足的情况下,可以使用双副本的机制,进行持久化。

如果不使用双副本机制,在持久化之后,机器宕机的情况下,再次使用持久化的数据的时候,需要重新计算得到数据;如果使用双副本机制,即使其中一个机器宕机,可以从另一个机器中获取数据,不需要重新计算。

这种方式,仅仅适用于内存资源极其充足的情况。