import org.apache.log4j.{Level, Logger}
import org.apache.spark.{SparkConf, SparkContext}
/**
* @author Jacky
* RDD持久化
*/
object Scala_PersistDemo {
def main(args: Array[String]): Unit = {
Logger.getLogger("org").setLevel(Level.WARN)
val conf = new SparkConf().setAppName("Scala_PersistDemo").setMaster("local")
val sc = new SparkContext(conf)
//加载文件,创建初始的RDD
val rdd1 = sc.textFile("E:\\wordcount.txt")
.flatMap(_.split(" ")).map((_, 1))
//对于一个被反复使用的RDD,我们应该对这个RDD进行持久化(缓存)。
//如果当这个RDD之后被再次使用,那么就不会重新开始计算,而是从缓存的数据中直接获取。
// rdd1.persist()
rdd1.cache() //通过查看源码,我们会发现cache()算子底层其实是调用persist(StorageLevel.MEMORY_ONLY),默认的持久化级别是持久化到内存中。
/**
* val NONE = new StorageLevel(false, false, false, false) 不进行持久化,也就是不起任何作用
* val DISK_ONLY = new StorageLevel(true, false, false, false) 将RDD的数据持久化保存到磁盘中
* val DISK_ONLY_2 = new StorageLevel(true, false, false, false, 2) 将RDD的数据持久化2份保存到磁盘上
*
* 将RDD的数据以Java纯对象的方式持久化保存到内存中,这种方式是最快的,也是Spark默认的持久化级别,
* 但是由于是以Java纯对象的方式进行保存,数据没有经过任何序列化压缩,所以内存不是足够大的时候,保存的数据量有限,
* 那么多余出来的数据保存不下就会被丢弃掉,下次再用到了没有保存的数据时就会重新开始计算。
* 比如,我们要持久化的RDD有50G,但是,我们的内存只能保存20G的数据,那么剩下的30G数据由于没有足够多的内存来保存,
* 那么这剩下的30G数据就会被丢弃,下次再次用到了这30G数据时,就会从头开始计算来获取这30G的数据,而另外20G的数据,
* 由于我们做了持久化保存到了内存中,就不需要再次进行计算了。
* val MEMORY_ONLY = new StorageLevel(false, true, false, true)
*
* 将RDD的数据持久化2份保存到内存中,当内存足够大的时候,希望从快速失败中恢复过来,可以采用这个持久化级别
* val MEMORY_ONLY_2 = new StorageLevel(false, true, false, true, 2)
* 将RDD中的数据经过序列化之后再保存到内存中,这种方式也是我们比较推荐的,因为当我们的内存不是足够大的时候,
* 那么我们可以采用这种方式。这种方式因为数据是经过序列化的,数据会小一些,内存保存的数据就多一些。
* 但是,这种持久化级别由于需要持久化的时候需要消耗CPU的性能来进行,同时取出来的时候还需要进行反序列化,
* 速度相较于MEMORY_ONLY这种持久化级别来说还不是特别快的。
* 由于这种序列化和反序列化都是在内存中完成,速度还是极快的,也是我们推荐使用的。
* val MEMORY_ONLY_SER = new StorageLevel(false, true, false, false)
* 将RDD的数据经过序列化后保存2份数据到内存中
* val MEMORY_ONLY_SER_2 = new StorageLevel(false, true, false, false, 2)
* 将RDD的数据持久化到内存中,如果内存保存不下那么多数据,那么就会将保存不下的数据持久化到磁盘上。
* val MEMORY_AND_DISK = new StorageLevel(true, true, false, true)
* 将RDD的数据持久化2份到内存中,如果内存保存不下那么多数据,那么就会将保存不下的数据持久化到磁盘上。
* val MEMORY_AND_DISK_2 = new StorageLevel(true, true, false, true, 2)
* 将RDD中的数据经过序列化之后保存到内存中,如果内存保存不下那么多数据,那么就会将保存不下的数据序列化持久化到磁盘上
* val MEMORY_AND_DISK_SER = new StorageLevel(true, true, false, false)
* 将RDD的数据经过序列化后保存2份数据到内存中,如果内存保存不下那么多数据,那么就会将保存不下的数据序列化持久化到磁盘上
* val MEMORY_AND_DISK_SER_2 = new StorageLevel(true, true, false, false, 2)
* 将数据保存到Spark的内存文件系统中去,数据由Spark自己来管理。
* 数据不是持久化到JVM的内存中,而是Spark自己维护的内存文件系统中。
* Off-Heap 堆外;非堆存储
* val OFF_HEAP = new StorageLevel(true, true, true, false, 1)
*/
//在Spark中,每触发一个action算子就触发了一个作业Job的提交。
var startTime = System.currentTimeMillis()
println(rdd1.countByKey())
var endTime = System.currentTimeMillis()
println(endTime - startTime) //2576
println("=========================")
startTime = System.currentTimeMillis()
println(rdd1.count())
endTime = System.currentTimeMillis()
println(endTime - startTime)
println("=========================") //606 74
startTime = System.currentTimeMillis()
println(rdd1.take(10000))
endTime = System.currentTimeMillis()
println(endTime - startTime) //112
//当我们的RDD使用完毕后,确定之后再也不会使用到这个RDD,
//那么我们可以将这个RDD持久化的数据进行释放,即移除持久化的数据
rdd1.unpersist()
sc.stop()
}
}