本文阐述了Spark中几种数据持久化方法Cache/Persist/Checkpoint的用法以及区别和联系,对于计算链条过长或者数据量较大的Spark任务有指导意义。原文来自:https://github.com/JerryLead/SparkInternals/blob/master/markdown/6-CacheAndCheckpoint.md
作为区别于 Hadoop 的一个重要 feature,cache 机制保证了需要访问重复数据的应用(如迭代型算法和交互式应用)可以运行的更快。与 Hadoop MapReduce job 不同的是 Spark 的逻辑/物理执行图可能很庞大,task 中 computing chain 可能会很长,计算某些 RDD 也可能会很耗时。这时,如果 task 中途运行出错,那么 task 的整个 computing chain 需要重算,代价太高。因此,有必要将计算代价较大的 RDD checkpoint 一下,这样,当下游 RDD 计算出错时,可以直接从 checkpoint 过的 RDD 那里读取数据继续算。
Cache 机制
回到 Overview 提到的 GroupByTest 的例子,里面对 FlatMappedRDD 进行了 cache,这样 Job 1 在执行时就直接从 FlatMappedRDD 开始算了。可见 cache 能够让重复数据在同一个 application 中的 jobs 间共享。
问题:哪些 RDD 需要 cache?
会被重复使用的(但不能太大)。
问题:如果cache数据量超过内存怎么办?
首先是内存有多大就缓存多少,当计算的时候,一部分从内存里边拿数据,一部分从磁盘拿数据
问题:怎么用cache?
rdd2.cache 然后rdd2. action(action 为抽象的)因为cache是transformation,只有遇到action时候才会真正的执行cache
问题:cache简单使用?
scala> val rdd1=sc.textFile("hdfs://hadoop01:9000/wc").flatMap(_.split(" ")).map((_,1)).reduceByKey(_+_)
rdd1: org.apache.spark.rdd.RDD[(String, Int)] = ShuffledRDD[4] at reduceByKey at <console>:27
scala> rdd1.cache
res2: rdd1.type = ShuffledRDD[4] at reduceByKey at <console>:27
scala> rdd1.collect
res3: Array[(String, Int)] = Array(((hello,3),1), ((,1),1), ((yu,1),1), ((nihao,1),1), ((dayu,1),1))
然后登陆:http://hadoop01:4040/storage/
结果如下:
说明缓存成功
问题:用户怎么设定哪些 RDD 要 cache?
因为用户只与 driver program 打交道,因此只能用 rdd.cache() 去 cache 用户能看到的 RDD。所谓能看到指的是调用 transformation() 后生成的 RDD,而某些在 transformation() 中 Spark 自己生成的 RDD 是不能被用户直接 cache 的,比如 reduceByKey() 中会生成的 ShuffledRDD、MapPartitionsRDD 是不能被用户直接 cache 的。
问题:driver program 设定 rdd.cache() 后,系统怎么对 RDD 进行 cache?
先不看实现,自己来想象一下如何完成 cache: