1、Cache缓存:
因为Spark中对每一个RDD执行的算子操作的时候,都需要从数据源头计算一遍,就会导致RDD被重复计算,浪费资源,消耗时间,影响整体的性能。
所以对于多次使用的RDD,可以使用Cache进行缓存
1、缓存默认是缓存到内存中
2、相当于persist(StorageLevel.MEMORY_ONLY),所以还可以通过指定persist结合StorageLevel来制定不同的缓存策略
对于使用的缓存策略是如何选择?
1、如果内存充足,直接使用MEMORY_ONLY
2、对于内存放不下:可以使用MEMORY_AND_DISK_SER,因为该模式可以对数据进行序列化,对数据具有一定的压缩的作用。
3、在使用结束的时候,需要释放资源
import org.apache.spark.rdd.RDD
import org.apache.spark.sql.SparkSession
import org.apache.spark.storage.StorageLevel
object Demo22Cache {
def main(args: Array[String]): Unit = {
val spark: SparkSession = SparkSession
.builder()
.appName(this.getClass.getSimpleName)
.master("local")
.getOrCreate()
/**
* 可以使用cache()对多次使用的RDD进行缓存
* 默认是缓存到内存中的
* 相当于persist(StorageLevel.MEMORY_ONLY)
* 所以还以通过persist结合StorageLevel来指定不同的缓存策略
*/
// stuMapRDD.cache()
/**
* 如何选择缓存策略:
* 1、如果内存充足:直接MEMORY_ONLY
* 2、如果内存放不下:使用MEMORY_AND_DISK_SER
* 为什么需要序列化?
* 可以尽可能的将数据缓存到内存中
* 序列化反序列化所消耗的时间对比磁盘IO来说,代价更小
*/
//读取学生的数据表
val stuRDD: RDD[String] = spark.sparkContext.textFile("spark/data/stu/students.txt")
//这里使用cache,默认的缓存策略是存储在内存中。
stuRDD.cache()
//还可以使用persist结合StorageLevel来指定对应的缓存策略
stuRDD.persist(StorageLevel.MEMORY_ONLY)
//统计班级的人数
stuRDD.map(kv=>(kv.split(",")(4),1)).reduceByKey(_+_).foreach(println)
//统计性别的人数:
stuRDD.map(kv=>(kv.split(",")(3),1)).reduceByKey(_+_).foreach(println)
// 用完之后记得释放缓存,特别是在实时程序中
stuRDD.unpersist()
while(true){
}
}
}
2、CheckPoint:
是一种容错容灾机制,就是将某一时间运行的数据或者是状态进行持久化。
import org.apache.spark.SparkContext
import org.apache.spark.rdd.RDD
import org.apache.spark.sql.SparkSession
object Demo23CheckPoint {
def main(args: Array[String]): Unit = {
def main(args: Array[String]): Unit = {
val spark: SparkSession = SparkSession
.builder()
.appName(this.getClass.getSimpleName)
.master("local")
.getOrCreate()
/**
* 1、在使用CheckPoint的之前需要通过sc设置一个目录
* 2、对于缓存是出于性能的角度,然而对于CheckPoint是出于可靠性的角度
* 3、ck一般会将数据存储到一些可靠的文件系统中,比如说HDFS中,然而对于缓存来说,会将数据尽可能的存储到内存中
* 4、ck在保存的时候需要单独触发一个Job完成,会从头开始把需要做ck的RDD计算出来并进行保存
* 相当于做ck的RDD被使用了多次,所以可以进行cache缓存来提高效率,这样ck就不要再从头计算了
* 5、ck实际上一般用于实时程序
*/
val sc: SparkContext = spark.sparkContext
sc.setCheckpointDir("spark/data/ck")
//读取学生的数据表
val stuRDD: RDD[String] = sc.textFile("spark/data/stu/students.txt")
stuRDD.checkpoint()
//统计班级的人数
stuRDD.map(kv => (kv.split(",")(4), 1)).reduceByKey(_ + _).foreach(println)
//统计性别的人数:
stuRDD.map(kv => (kv.split(",")(3), 1)).reduceByKey(_ + _).foreach(println)
}
}
}
CheckPoint 的执行原理:
当RDD的job执行完毕后,会从最后一个RDD往前回溯
当回溯到某个RDD调用了checkpoint方法后,Spark会启动一个新的job
该任务会重新计算该RDD的数据,并持久化到HDFS上
优化:对执行了checkpoint操作的RDD先进行Cache缓存,避免重复计算
3、Cache缓存对比CheckPoint检查点
4、Lineage血统
Spark中解决节点失效、数据丢失等问题时采用的一种机制或方案 为了保证RDD 中数据的鲁棒性,RDD数据集通过所谓的血统关系(Lineage)记住了它是如何从其它RDD中演变过来的
相比其它系统的细粒度容错机制
内存数据更新级别的备份或者LOG机制
Redis中的RDB策略
HBase的WAL机制
RDD的Lineage记录的是粗粒度的
RDD之间的转换操作都会会被记录
例如filter, map, join等操作都会被记录
有点类似Redis中的AOF策略
当RDD的分区数据丢失时 ,可通过Lineage来重新运算并恢复丢失的数据
宽依赖的分区数据重算开销要远大于窄依赖