1. RDD Cache缓存
RDD通过Cache或者Persist方法将前面的计算结果缓存,默认情况下会把数据以序列化的形式缓存在JVM的堆内存中。但是并不是这两个方法被调用时立即缓存,而是触发后面的action时,该RDD将会被缓存在计算节点的内存中,并供后面重用。
- cache在底层调用的还是Persist方法
def cache(): this.type = persist()
def persist(): this.type = persist(StorageLevel.MEMORY_ONLY)
- 注意:虽然叫持久化,但是当应用程序程序执行结束之后,缓存的目录也会被删除
- 实际场景下,我们一般不会持久化到磁盘上,性能是一方面,另外一方面,因为是分布式的,有可能持久化到某个节点,那么无法保证其它节点也会同样持久化。
缓存实例:
object Spark01_cache {
def main(args: Array[String]): Unit = {
//创建SparkConf并设置App名称
val conf: SparkConf = new SparkConf().setAppName("SparkCoreTest").setMaster("local[*]")
//创建SparkContext,该对象是提交Spark App的入口
val sc: SparkContext = new SparkContext(conf)
//创建RDD
val rdd: RDD[String] = sc.makeRDD(List("hello bangzhang","hello jingjing"),2)
//扁平映射
val flatMapRDD: RDD[String] = rdd.flatMap(_.split(" "))
//结构转换
val mapRDD: RDD[(String, Int)] = flatMapRDD.map {
word => {
println("********************")
(word, 1)
}
}
//打印血缘关系
println(mapRDD.toDebugString)
//对RDD的数据进行缓存 底层调用的是persist函数 默认缓存在内存中
mapRDD.cache()
//persist可以接收参数,指定缓存位置
//注意:虽然叫持久化,但是当应用程序程序执行结束之后,缓存的目录也会被删除
//mapRDD.persist()
//mapRDD.persist(StorageLevel.DISK_ONLY)
//触发行动操作
mapRDD.collect()
println("---------------------------------------")
//打印血缘关系
println(mapRDD.toDebugString)
//触发行动操作
mapRDD.collect()
// Thread.sleep(1000000000);
// 关闭连接
sc.stop()
}
}
缓存级别
mapRdd.cache()
def cache(): this.type = persist()
def persist(): this.type = persist(StorageLevel.MEMORY_ONLY)
object StorageLevel {
val NONE = new StorageLevel(false, false, false, false)
val DISK_ONLY = new StorageLevel(true, false, false, false)
val DISK_ONLY_2 = new StorageLevel(true, false, false, false, 2)
val MEMORY_ONLY = new StorageLevel(false, true, false, true)
val MEMORY_ONLY_2 = new StorageLevel(false, true, false, true, 2)
val MEMORY_ONLY_SER = new StorageLevel(false, true, false, false)
val MEMORY_ONLY_SER_2 = new StorageLevel(false, true, false, false, 2)
val MEMORY_AND_DISK = new StorageLevel(true, true, false, true)
val MEMORY_AND_DISK_2 = new StorageLevel(true, true, false, true, 2)
val MEMORY_AND_DISK_SER = new StorageLevel(true, true, false, false)
val MEMORY_AND_DISK_SER_2 = new StorageLevel(true, true, false, false, 2)
val OFF_HEAP = new StorageLevel(true, true, true, false, 1)
注意:默认的存储级别都是仅在内存存储一份。在存储级别的末尾加上“_2”表示持久化的数据存为两份。
缓存有可能丢失,或者存储于内存的数据由于内存不足而被删除,RDD的缓存容错机制保证了即使缓存丢失也能保证计算的正确执行。通过基于RDD的一系列转换,丢失的数据会被重算,由于RDD的各个Partition是相对独立的,因此只需要计算丢失的部分即可,并不需要重算全部Partition。
自带缓存的算子:
Spark会自动对一些Shuffle操作的中间数据做持久化操作(比如:reduceByKey)。这样做的目的是为了当一个节点Shuffle失败了避免重新计算整个输入。但是,在实际使用的时候,如果想重用数据,仍然建议调用persist或cache。
2. RDD CheckPoint检查点
- 检查点:是通过将RDD中间结果写入磁盘。
- 为什么要做检查点?
由于血缘依赖过长,造成容错代价过大(相当于从头再来,成本自然高了),这样就不如在中间
阶段做检查点容错,如果检查点之后节点出现问题,直接从检查点开始重做血缘,减少开销。
- 检查点的数据存放?
CheckPoint的数据一般存放在HDFS等容错,高可用的文件系统上
- 检查点数据存储格式?
二进制文件
- 检查点切断血缘:
在Checkpoint的过程中,该RDD的所有依赖于父RDD中的信息将全部被移除。
- 检查点的触发时机/时间?
必须要action操作才能触发,但是血缘关系为了数据安全,会从血缘关系的最开始执行一遍。
7. 设置检查点步骤
- 设置检查点数据存储路径:sc.setCheckpointDir("./checkpoint1")
- 设置检查点方法:wordToOneRdd.checkpoint()
- 设置检查点案例
在开发环境,一般检查点和缓存配合使用
object Spark02_checkpoint {
def main(args: Array[String]): Unit = {
//创建SparkConf并设置App名称
val conf: SparkConf = new SparkConf().setAppName("SparkCoreTest").setMaster("local[*]")
//创建SparkContext,该对象是提交Spark App的入口
val sc: SparkContext = new SparkContext(conf)
//设置检查点目录
sc.setCheckpointDir("D:\\dev\\workspace\\bigdata-0105\\spark-0105\\cp")
//开发环境,应该将检查点目录设置在hdfs上
// 设置访问HDFS集群的用户名
//System.setProperty("HADOOP_USER_NAME","mayi")
//sc.setCheckpointDir("hdfs://hadoop202:8020/cp")
//创建RDD
val rdd: RDD[String] = sc.makeRDD(List("hello bangzhang","hello jingjing"),2)
//扁平映射
val flatMapRDD: RDD[String] = rdd.flatMap(_.split(" "))
//结构转换
val mapRDD: RDD[(String, Long)] = flatMapRDD.map {
word => {
(word, System.currentTimeMillis())
}
}
//打印血缘关系
println(mapRDD.toDebugString)
//在开发环境,一般检查点和缓存配合使用
mapRDD.cache()
//设置检查点
mapRDD.checkpoint()
//触发行动操作
mapRDD.collect().foreach(println)
println("---------------------------------------")
//打印血缘关系
println(mapRDD.toDebugString)
//释放缓存
//mapRDD.unpersist()
//触发行动操作
mapRDD.collect().foreach(println)
// 关闭连接
sc.stop()
}
}
3. 缓存和检查点的区别?
- 1)Cache缓存只是将数据保存起来,不切断血缘依赖。Checkpoint检查点切断血缘依赖。
- 2)Cache缓存的数据通常存储在磁盘、内存等地方,可靠性低。Checkpoint的数据通常存储在HDFS等容错、高可用的文件系统,可靠性高。
- 3)建议对checkpoint()的RDD使用Cache缓存,这样checkpoint的job只需从Cache缓存中读取数据即可,否则需要再从头计算一次RDD。
- 4)如果使用完了缓存,可以通过unpersist()方法释放缓存