Spark RDD
RDD及其特点
-
RDD是Spark的核心数据抽象,全称是Resillient Distributed Dataset,及其弹性分布式数据集。
-
从抽象层面上来看RDD就是一种不可变的(immutable)分布式的元素集合。一个RDD包含多个分区,每个分区散落在Spark集群的多个节点上,因此可以对RDD的数据进行并行操作,这就是RDD分布式的体现。
-
在应用程序中可以使用集合来创建RDD,也可以导入外部数据源来创建RDD,例如:本地文件、HDFS、Hive或HBase等。
-
此外,RDD具有容错性,这也是RDD最重要的特性。RDD本身具有Lineage机制,它会记录每个RDD与其父RDD之间的关联,即父RDD是通过什么操作才生成该RDD。RDD的immutable特性,再加上Lineage机制,使得RDD具备了容错性。比如说:某个节点的 RDD partition因为机器故障导致数据丢失,那么RDD会自动通过自己的父RDD重新计算该RDD partition。
-
RDD中的数据默认存储在内存中,当内存不足时,Spark会自动将RDD数据写入磁盘。
RDD的弹性表现
-
自动进行内存和磁盘的数据存储的切换
-
Lineage机制高效容错,即第n个节点出错,从第n-1个节点恢复
-
Task失败会进行特定次数的重试(默认4次)
-
Stage失败会进行特定次数的重试,只计算失败的数据分片
-
checkpoint和persist
-
数据调度弹性,DAG Task和资源调度无关
-
数据分片的高度弹性(人工自由设置分片函数),repartition
Spark中RDD的执行流程
RDD分区
RDD 内部的数据集合在逻辑上和物理上被划分成多个小子集合,这样的每一个子集合我们将其称为分区,分区的个数会决定并行计算的粒度,而每一个分区数值的计算都是在一个单独的Task中进行,因此并行任务的个数,也是由 RDD分区的个数决定的。
RDD转化操作
RDD的转化操作时返会一个新的RDD的操作,而且许多的转化操作都是针对RDD中的一个元素。通过转化操作,可以从已有的RDD中得到新的RDD,同时Spark会使用Lineage Graph(谱系图)来记录这些不同RDD之间的依赖。Spark需要用这些信息来按需计算每个RDD,也可以依靠Lineage Graph在持久化的RDD丢失部分数据时,来重新计算。
val RDD1 = sc.textFile("file:///root/data/users.csv")
val RDD2 = RDD1.map(_.split(","))
RDD行动操作
RDD行动操作会进行实际的计算,并且会连同之前的转化操作一起执行。最终求得的结果会返回给驱动器程序,或者写入外部文件系统。
val RDD1 = sc.textFile("file:///root/data/users.csv")
val RDD2 = RDD1.map(_.split(","))
val RDD3 = RDD2.take(10)
惰性求值
RDD的转化操作都是惰性求值,也就是说,我们对RDD调用转换操作时,操作不会立即执行,Spark会在内部记录下所要执行的操作的相关信息,当调用到行动操作,才会触发实际的运算。由于Spark的惰性求值,我们就可以把一些操作合并起来从而减少计算数据的步骤。