文章目录
一、RDD持久化
(一)引入持久化的必要性
Spark中的RDD是懒加载的,只有当遇到行动算子时才会从头计算所有RDD,而且当同一个RDD被多次使用时,每次都需要重新计算一遍,这样会严重增加消耗。为了避免重复计算同一个RDD,可以将RDD进行持久化。
Spark中重要的功能之一是可以将某个RDD中的数据保存到内存或者磁盘中,每次需要对这个RDD进行算子操作时,可以直接从内存或磁盘中取出该RDD的持久化数据,而不需要从头计算才能得到这个RDD。
(二)案例演示持久化操作
1、RDD的依赖关系图
2、不采用持久化操作
查看要操作的文件
启动Spark Shell
按照图示进行操作,得RDD4和RDD5
计算RDD4,会RDD1到RDD2到RDD3到RDD4跑一趟,查看结果
计算RDD5,也会RDD1到RDD2到RDD3到RDD4跑一趟,查看结果
3、采用持久化操作
计算到RDD3时,标记持久化
计算RDD4,就是基于RDD3缓存的数据开始计算,不用从头到尾跑一趟
计算RDD5,就是基于RDD3缓存的数据开始计算,不用从头到尾跑一趟
二、存储级别
(一)持久化方法的参数
利用RDD的persist()方法实现持久化,向persist()方法中传入一个StorageLevel对象指定存储级别。每个持久化的RDD都可以使用不同的存储级别存储,默认的存储级别是StorageLevel.MEMORY_ONLY。
(二)Spark RDD存储级别表
(三)如何选择存储级别 - 权衡内存使用率和CPU效率
如果RDD存储在内存中不会发生溢出,那么优先使用默认存储级别(MEMORY_ONLY),该级别会最大程度发挥CPU的性能,使在RDD上的操作以最快的速度运行。
如果RDD存储在内存中会发生溢出,那么使用MEMORY_ONLY_SER并选择一个快速序列化库将对象序列化,以节省空间,访问速度仍然相当快。
除非计算RDD的代价非常大,或者该RDD过滤了大量数据,否则不要将溢出的数据写入磁盘,因为重新计算分区的速度可能与从磁盘读取分区一样快。
如果希望在服务器出故障时能够快速恢复,那么可以使用多副本存储级别MEMORY_ONLY_2或MEMORY_AND_DISK_2。该存储级别在数据丢失后允许在RDD上继续运行任务,而不必等待重新计算丢失的分区。其他存储级别在发生数据丢失后,需要重新计算丢失的分区。
(四)查看persist()与cache()方法源码
/**
* 在第一次行动操作时持久化RDD,并设置存储级别,当RDD从来没有设置过存储级别时才能使用该方法
*/
def persist(newLevel: StorageLevel): this.type = {
if (isLocallyCheckpointed) {
// 如果之前已将该RDD设置为localCheckpoint,就覆盖之前的存储级别
persist(LocalRDDCheckpointData.transformStorageLevel(newLevel), allowOverride = true)
} else {
persist(newLevel, allowOverride = false)
}
}
/**
* 持久化RDD,使用默认存储级别(MEMORY_ONLY)
*/
def persist(): this.type = persist(StorageLevel.MEMORY_ONLY)
/**
* 持久化RDD,使用默认存储级别(MEMORY_ONLY)
*/
def cache(): this.type = persist()
(五)案例演示设置存储级别
在net.py.rdd包里创建TestPersist对象
package net.py.rdd
import org.apache.log4j.{Level, Logger}
import org.apache.spark.{SparkConf, SparkContext}
import org.apache.spark.rdd.RDD
object TestPersist {
def main(args: Array[String]): Unit = {
// 创建Spark配置对象
val conf = new SparkConf()
conf.setAppName("TestPersist")
.setMaster("local")
.set("spark.testing.memory", "2147480000")
// 基于配置创建Spark上下文
val sc = new SparkContext(conf)
// 去除Spark运行信息
Logger.getLogger("org").setLevel(Level.OFF)
Logger.getLogger("com").setLevel(Level.OFF)
System.setProperty("spark.ui.showConsoleProgress", "false")
Logger.getRootLogger().setLevel(Level.OFF)
//创建RDD
val rdd: RDD[Int] = sc.parallelize(List(100, 200, 300, 400, 500))
//将RDD标记为持久化,默认存储级别为StorageLevel.MEMORY_ONLY
rdd.persist()
// rdd.persist(StorageLevel.DISK_ONLY) //持久化到磁盘
// rdd.persist(StorageLevel.MEMORY_AND_DISK)//持久化到内存,将溢出的数据持久化到磁盘
// 第一次行动算子计算时,将对标记为持久化的RDD进行持久化操作
val result: String = rdd.collect().mkString(", ")
println(result)
// 第二次行动算子计算时,将直接从持久化的目的地读取数据进行操作,而不需要从头计算数据
rdd.collect().foreach(println)
}
}
三、利用Spark WebUI查看缓存
(一)创建RDD并标记为持久化
(二)Spark WebUI查看RDD存储信息
执行命令:rdd.collect(),收集RDD数据
执行以下命令,创建rdd2,并将rdd2持久化到磁盘