Spark RDD弹性分布式数据集——RDD的机制

目录

3.6     RDD机制

3.6.1  持久化机制

3.6.2  容错机制


3.6     RDD机制

       Spark为RDD提供了两个重要的机制,分别是持久化机制(即缓存机制)容错机制

3.6.1  持久化机制

       在Spark中,RDD是采用惰性求值,即每次调用行动算子操作,都会从头开始计算。然而,每次调用行动算子操作,都会触发一次从头开始的计算,这对于迭代计算来说,代价是很大的,因为迭代计算经常需要多次重复的使用同一组数据集,所以,为了避免重复计算的开销,可以让Spark对数据集进行持久化。

       通常情况下,一个RDD是由多个分区组成的,RDD中的数据分布在多个节点中,因此,当持久化某个RDD时,每一个节点都将把计算分区的结果保存在内存中,若对该RDD或衍生出的RDD进行其他行动算子操作时,则不需要重新计算,直接去取各个分区保存的数据即可,这使得后续的行动算子操作更快(通常超过10倍),并且缓存是Spark构建迭代式算法和快速交互式查询的关键。

       RDD的持久化操作有两种方法,分别是cache()方法persist()方法每一个持久化的RDD都可以使用不同的存储级别存储,从而允许持久化数据集在硬盘或者内存中作为序列化的Java对象存储,甚至可以跨节点复制。

       Persist()方法的存储级别是通过StorageLevel对象(Scala、Java、Python)设置的。

       Cache()方法的存储级别是使用默认的存储级别(即StorageLevel.MEMORY_ONLY(将反序列化的对象存入内存))。

       持久化RDD的存储级别:

Spark RDD弹性分布式数据集——RDD的机制_第1张图片

 

1.使用persist()方法对RDD进行持久化

       定义一个列表list,通过该列表创建一个RDD,然后通过persist持久化操作和算子操作统计RDD中的元素个数以及打印输出RDD中的所有元素。

代码:

org.apache.spark.storage.StorageLevel
val list = List(“Anything”, “is”, “OK”)
val listRDD = sc.parallelize(list)
listRDD.persist(StorageLevel.DISK_ONLY)
println(listRDD.count())
println(listRDD.collect().mkString(","))
  1. org.apache.spark.storage.StorageLevel
  2. val list = List(“Anything”, “is”, “OK”)
  3. val listRDD = sc.parallelize(list)
  4. listRDD.persist(StorageLevel.DISK_ONLY)
  5. println(listRDD.count())
  6. println(listRDD.collect().mkString(","))

Spark RDD弹性分布式数据集——RDD的机制_第2张图片

 

代码理解:

       第1行代码导入了StorageLevel对象的包;第2行代码定义了一个列表list;第3行代码执行sc.parallelize(list)操作,创建了一个RDD,即listRDD,第4行代码添加了persist()方法,用于持久化RDD,减少I/O操作,提高计算效率;第5行代码执行listRDD.count()行动算子操作,将统计listRDD中元素的个数;第6行代码执行了listRDD.collect()行动算子操作和mkString(”,”)操作,将listRDD中的所有元素进行打印输出,并且以逗号为分隔符。

注意:当程序执行至第4行代码listRDD.persist(StorageLevel.DISK_ONLY)时,并不会持久化listRDD,因为listRDD还没被真正的计算;当执行至第5行代码println(listRDD.count())时,listRDD才会进行第一次行动算子操作,触发真正的从头到尾的计算,这个时候listRDD.persist()方法才会被真正的执行,把listRDD持久化到磁盘中;当执行至第6行代码时,进行第二次行动算子操作,但不触发从头到尾的计算,只需使用已经进行持久化的listRDD()来进行计算。

2.使用cache()方法对RDD进行持久化

   定义一个列表list,通过该列表创建一个RDD,然后通过cache持久化操作和算子操作统计RDD中的元素个数以及打印输出RDD中的所有元素。

代码:

val list = List(“Anything”, “is”, “OK”)
val listRDD = sc.parallelize(testlist)
listRDD.cache()
println(listRDD.count())
println(listRDD.collect().mkString(","))
  1. val list = List(“Anything”, “is”, “OK”)
  2. val listRDD = sc.parallelize(testlist)
  3. listRDD.cache()
  4. println(listRDD.count())
  5. println(listRDD.collect().mkString(","))

Spark RDD弹性分布式数据集——RDD的机制_第3张图片

代码理解:

第3行代码listRDD.cache()对listRDD进行持久化操作,即添加cache()方法,用于持久化RDD,减少I/O操作,提高计算效率。然而,使用cache()方法进行持久化操作,底层时调用了persist(MEMORY_ONLY)方法,用来对RDD进行持久化。当程序执行至第3行代码listRDD.cache()时,并不会持久化listRDD,因为listRDD还没被真正的计算;当执行至第4行代码println(listRDD.count())时,listRDD才会进行第一次行动算子操作,触发真正的从头到尾的计算,这个时候listRDD.persist()方法才会被真正的执行,把listRDD持久化到内存中;当执行至第5行代码时,进行第二次行动算子操作,但不触发从头到尾的计算,只需使用已经进行持久化的listRDD()来进行计算。

3.6.2  容错机制

       当Spark集群中的某一个节点由于宕机导致数据丢失,可以通过Spark中的RDD容错机制恢复已经丢失的数据。RDD提供了两种故障恢复的方式,分别是血统(lineage)方式设置检查点(checkpoint)方式

血统方式主要是根据RDD之间的依赖关系对丢失数据的 RDD 进行数据恢复。如果丢失数据的子RDD在进行窄依赖运算,则只需要把丢失数据的父RDD的对应分区进行重新计算即可,不需要依赖其他的节点,并且在计算过程中不会存在冗余计算;若丢失数据的子RDD进行宽依赖运算,则需要父RDD的所有分区都要进行从头到尾的计算,在计算过程中会存在冗余计算。为了解决宽依赖运算中出现的计算冗余问题,Spark又提供了另一种方式进行数据容错,即设置检查点方式。

设置检查点方式本质上是将RDD写入磁盘进行存储。当RDD在进行宽依赖运算时,只需要在中间阶段设置一个检查点进行容错,即通过 Spark中的sparkContext 对象调用setCheckpoint()方法,设置一个容错文件系统目录(如HDFS)作为检查点checkpoint,将 checkpoint的数据写人之前设置的容错文件系统中进行高可用的持久化存储,若是后面有节点出现宕机导致分区数据丢失,则可以从作为检查点的RDD开始重新计算,不需要进行从头到尾的计算,这样可以减少开销


总结

        以上就是今天要讲的内容,本文介绍了Spark RDD弹性分布式数据集——RDD的机制,而若想需要深入学习,可配合一些网络资源进行学习,同时需要在Spark中进行实践练习,加深巩固!

你可能感兴趣的:(Spark,Scala,spark,大数据,big,data)