Spark中缓存和检查点的区别???
一、缓存
cache和persist是RDD的两个API,cache底层调用的就是persist,区别在于cache不能指定缓存方式,只能缓存在内存中,但是persist可以指定缓存方式,比如:缓存在内存中、内存和磁盘并序列化等。同时不会切断RDD的血缘关系,当Executor发生宕机时,会重新根据依赖关系读取数据。
二、checkpoint
本质上是将RDD(数据)长久地保存在磁盘文件,从而做检查点(通常是checkpoint到HDFS上)。在生产环境中,往往在RDD上会执行各种操作,使得DAG图会拉的非常长,为防止中间某个环节出问题而影响正常的计算,会使用checkpoint机制将重要的RDD存到HDFS上,这样,出错以后就不必要回到最初的RDD重新计算,而是可以直接从checkpoint位置重新运算。
三、缓存和检查点的区别
1、都是lazy操作,只有action算子触发以后才会真正的进行缓存或者checkpoint。lazy操作时Spark的一个重要特性,不仅适用于RDD还适用于Spark SQL。
2、cache只缓存数据,不改变lineage(血缘),但比较容易丢失数据。
3、checkpoint改变原有的lineage(血缘),生成新的checkpointRDD,通常存于HDFS中,因为可以利用 HDFS 多副本特性保证容错
Examples:
1.缓存cache()的使用
object Test01 {
def main(args: Array[String]): Unit = {
val sc = new SparkContext(new SparkConf().setAppName("Demo").setMaster("local"))
val rdd1 = sc.textFile("file:///D:\\IdeaProgram\\Bigdata\\file\\Spark\\wc\\input")
//在这里设置一个cache缓存,只缓存结果,建议缓存完之后执行action,再去执行转换算子+执行算子
val rdd2 = rdd1.flatMap(_.split("\\s+")).map((_, 1)).reduceByKey(_ + _).cache()
//这里如果不设置缓存,每次执行完一个action以后再去执行下一个action的时候都要从头开始进行计算
//如果设置了缓存,每次执行完一个action以后再去执行下一个action的时候直接从缓存为止读取数据
rdd2.collect()
rdd2.foreach(println(_))
rdd2.take(2)
}
}
2.persist()的使用
import org.apache.spark.storage._
def main(args: Array[String]): Unit = {
val conf = new SparkConf().setMaster("local").setAppName("DISK_ONLY")
val sc = new SparkContext(conf);
sc.setLogLevel("ERROR")
val a = sc.parallelize(1 to 9, 3).persist(StorageLevel.DISK_ONLY)
println(a.first())
}
一旦 driver program 执行结束,也就是 executor 所在进程 CoarseGrainedExecutorBackend stop,blockManager也会stop;被缓存到磁盘上的RDD也会被清空(整个blockManager使用的local文件夹被删除 )。
3.checkpoint()的使用
checkpoint检查点机制
检查点(本质就是通过将RDD写入Disk做检查点)是为了通过lineage(血统)做容错的辅助,lineage过长会造成容错成本过高,这样就不如在中间阶段做检查点容错,如果之后有节点问题而丢失分区,从做查点的RDD开始重做lineage,就会减少开销检查点通过将数据写入到HDFS文件系统实现了RDD的检查点功能.
检查点,类似于快照,chekpoint的作⽤就是将DAG中⽐较重要的数据做⼀个检查点,将结果存储到⼀个⾼可⽤的地⽅
//检查点的使用
def main(args: Array[String]): Unit = {
val conf = new SparkConf().setAppName("SparkDemo").setMaster("local")
val sc = new SparkContext(conf)
//设置检查点的路径
sc.setCheckpointDir("hdfs://hadoop01:8020/ck")
val rdd = sc.textFile("hdfs://hadoop01:8020/word.txt").flatMap(_.split(" ")).map((_,1)).reduceByKey(_+_)
//检查点的触发⼀定要使⽤个action算⼦
rdd.checkpoint()
rdd.saveAsTextFile("hdfs://hadoop01:8020/out10")
println(rdd.getCheckpointFile) //查看存储的位置
/**
查看是否可以设置检查点 rdd.isCheckpointed 这个⽅法在shell中可以使⽤ 但是代码中不好⽤
*/
}
4、使用心得体会
缓存和检查点的区别
缓存把RDD计算出来的然后放在内存,但是RDD的依赖链不能丢掉,当某个exexutor宕机时,上面cache的RDD就会丢掉,需要通过依赖链放入重新计算,不同的是,checkpoint是把RDD保存在HDFS上,是多副本可靠存储,所以依赖链可以丢掉,就是斩断了依赖链,是通过复制实现的高容错
cache和persist的比较
1.cache底层调用的是persist
2.cache默认持久化等级是内存且不能修改,persist可以修改持久化的等级
什么时候使用cache或checkpoint
1.某步骤计算特别耗时
2.计算链条特别长
3.发生shuffle之后
一般情况建议使用cache或是persist模式,因为不需要创建存储位置,默认存储到内存中计算速度快,而checkpoint需要手动创建存储位置和手动删除数据,若数据量非常庞大建议使用checkpoint
Task包括ResultTask(最后一个阶段的任务) + ShuffleMapTask(非最后一个阶段)