3. 持久化
持久化,也就是将 RDD 的数据缓存到内存中/磁盘中,以后无论对这个RDD做多少次计算,都是直接取这个RDD的持久化的数据,比如从内存中或者磁盘中,直接提取一份数据。可以使用 persist()函数来进行持久化,一般默认的存储空间是在内存中,如果内存不够就会写入磁盘中。persist 持久化分为不同的等级,还可以在存储等级的末尾加上_2用于把持久化的数据存为 2 份,避免数据丢失。
下面的列表列出了不同的持久化等级:
还可以执行rdd.unpersist()
清除缓存
import org.apache.spark.storage._ val rdd = sc.makeRDD(1 to 100000) rdd.persist(StorageLevel.MEMORY_AND_DISK_SER_2) rdd.take(15) rdd.unpersist()
提示:其实缓存 cache()
底层就是调用的persist()
的无参版本,执行的是:persist(MEMORY_ONLY)
。
对于persist()
方法而言,我们可以根据不同的业务场景选择不同的持久化级别,具体介绍如下表:
持久化对于性能调优的原则
尽可能地去复用RDD,差不多的RDD,可以抽取称为一个共同的RDD,反复使用,比如拥有一个key-value型RDD,后面又需要用到拥有同样value的RDD,则可以复用key-value型的RDD即可。
对于要多次计算和使用的公共RDD,一定要进行持久化。
持久化,是可以进行序列化的。如果正常将数据持久化在内存中,那么可能会导致内存的占用过大,进而可能会导致OOM内存溢出。此时就可以选择序列化的方式在纯内存中存储。将RDD的每个partition的数据,序列化成一个大的字节数组,可以大大减少内存的空间占用。 序列化的方式,唯一的缺点就是:在获取数据的时候,机器内部需要反序列化。 如果序列化纯内存方式,还是导致OOM,内存溢出;就只能考虑磁盘的方式,内存+磁盘的普通方式(无序列化或者序列化)。
如果要求数据的高可靠性,可以使用双副本机制进行持久化。一个副本丢了,不用重新计算,还可以使用另外一份副本。
4. persist()的两个坑
请参考此教程:关于 Spark persist() 的两个坑
0xFF 总结
- 能够转化算子的时候尽量使用转化算子,少用行动算子,这是性能调优的一个小技巧。
- 其实能不使用
DISK
相关的持久化策略,就不要使用,有时从磁盘里读取数据,还不如重新计算一次。 - 请继续学习本博客其他教程!