一、RDD的缓存(持久化)
RDD的缓存有两种方法
(1)cache()
(2)persist()
如果需要自定义缓存等级,那么使用persist(),cache()的缓存等级为MEMORY_ONLY
,使用cache()的缺点是:机器宕机则会内存数据丢失、内存溢出
使用比较多的缓存等级为MEMORY_AND_DISK
使用spark-shell --master spark: (集群模式)测试是否有缓存
通过查看webUI8080端口可以查看缓存在内存中的数据,在DAG有向图中显示为绿色
host01::8080
host01:4040 (4040端口和历史作业服务器4000端口很像,区别在于4040端口是用于查看正在进行的job历史的)
在使用Action算子之前是无法查看到缓存信息的,所以可以使用collect或者foreach等算子之后再查看该页面
下面的方式也能查看是否有缓存出现
注意查看关键字cache关键字
我们可以对缓存的RDD对象做多次Action算子操作,可以看到该页面的中所用到的时间会缩短,从而可以看到缓存带来的效率提升!
随便点进一个job,可以查看其DAG图,可以看出该job是在filter中的缓存中提取数据的
缓存使⽤的场景:通常会将后期常⽤的数据进⾏缓存
特别是发⽣shuffle后的数据,因为shuffle过程的代价太⼤,所以经常在shuffle后进⾏缓存
cache默认是缓存到内存中,cache是transformation函数,所以需要⼀个action算⼦触发
import org.apache.spark.rdd.RDD
import org.apache.spark.storage.StorageLevel
import org.apache.spark.{SparkConf, SparkContext}
/**
* RDD的缓存:
* cache():
* 调用的persist()方法,实现的缓存。无法修改缓存等级。
* persist():
* 可以修改缓存的等级。
*/
object _01_CacheAndPresist {
System.setProperty("HADOOP_USER_NAME","root")
private val sc: SparkContext = new SparkContext(new SparkConf().setMaster("local").setAppName("cache"))
def main(args: Array[String]): Unit = {
val rdd: RDD[Int] = sc.parallelize(Array(1, 2, 3, 4, 5))
val rdd1: RDD[Int] = rdd.map(_ * 2).persist(StorageLevel.MEMORY_AND_DISK)
val rdd2: RDD[Int] = rdd1.filter(_ % 3 == 0).cache()
rdd2.foreach(println)
val res: Array[Int] = rdd2.collect()
val count: Long = rdd2.count()
val sum: Double = rdd2.sum()
// 手动释放内存
rdd2.unpersist()
rdd1.saveAsTextFile("hdfs://host01:9000/10-11/test")
}
}
二、checkpoint检查点机制
检查点(本质是通过将RDD写⼊Disk做检查点)是为了通过lineage(血缘)做容错的辅助,lineage过⻓会造成容错成本过⾼,这样就不如在中间阶段做检查点容错,如果之后有节点出现问题⽽丢失分区,从做检查点的RDD开始重做Lineage,就会减少开销。
检查点通过将数据写⼊到HDFS⽂件系统实现了RDD的检查点功能。
检查点,类似于快照,chekpoint的作⽤就是将DAG中⽐较重要的数据做⼀个检查点,将结果存储到⼀个⾼可⽤的地⽅
(1)设置检查点存放路径
sc.setCheckpointDir("hdfs://host01:8020/ck")
(2)制作检查点
rdd.checkpoint()
(3)查看检查点
println(rdd.getCheckpointFile) //查看存储的位置,该方法应该放在Action算子后面,只有当Action算子完成后才能查看检查点
(4)查看是否可以设置检查点
rdd.isCheckpointed //这个⽅法在shell中可以使⽤ 但是代码中不好⽤
import org.apache.spark.rdd.RDD
import org.apache.spark.{SparkConf, SparkContext}
/**
* 设置检查点
*/
object _02_CheckPoint {
System.setProperty("HADOOP_USER_NAME", "root")
private val sc: SparkContext = new SparkContext(new SparkConf().setMaster("local").setAppName("cache"))
sc.setCheckpointDir("hdfs://host01/checkpoint")
def main(args: Array[String]): Unit = {
val rdd: RDD[String] = sc.textFile("C:\\Users\\luds\\Desktop\\wcFile")
val rdd1: RDD[(String, Int)] = rdd.flatMap(_.split("[ \t]+")).map((_, 1)).reduceByKey(_ + _)
// 制作一个checkpoint
rdd1.checkpoint()
rdd1.foreach(println)
}
}
三、cache和checkpoint比较
checkpoint的数据需要⼿动清除⽽cache的数据是⾃动清除的(任务结束)
创建⼀个rdd之后,直接连续调⽤cache()或者persist()才可以,如果先创建⼀个rdd,再单独另起⼀⾏执
⾏cache()或者persist(),是没有用的,⽽且会报错,⼤量的⽂件会丢失