RDD

Posted on 2017-11-06 14:32  打杂滴  阅读(437)  评论(0编辑  收藏  举报

RDD,全称为Resilient Distributed Datasets,是一个容错的、并行的数据结构,可以让用户显式地将数据存储到磁盘和内存中,并能控制数据的分区。同时,RDD还提供了一组丰富的操作来操作这些数据。在这些操作中,诸如map、flatMap、filter等转换操作实现了monad模式,很好地契合了Scala的集合操作。除此之外,RDD还提供了诸如join、groupBy、reduceByKey等更为方便的操作(注意,reduceByKey是action,而非transformation),以支持常见的数据运算。

“弹性”是指在任何时候都能进行重算。这样当集群中的一台机器挂掉而导致存储在其上的RDD丢失后,Spark还可以重新计算出这部分的分区的数据。但用户感觉不到这部分的内容丢失过。这样RDD数据集就像块带有弹性的海绵一样,不管怎样挤压(分区遭到破坏)都是完整的。

Spark 中的RDD 就是一个不可变的分布式对象集合。每个RDD 都被分为多个分区,这些
分区运行在集群中的不同节点上。RDD 可以包含Python、Java、Scala 中任意类型的对象,
甚至可以包含用户自定义的对象。

用户可以使用两种方法创建RDD:1.读取一个外部数据集,或在驱动器程序里分发驱动器程
序中的对象集合(比如list 和set)。2.由一个RDD 生成一个新的RDD

RDD 支持两种类型的操作: 转化操作(transformation) 和行动操作 (action)。

转化操作会由一个RDD 生成一个新的RDD。

行动操作会对RDD 计算出一个结果,并把结果返回到驱动器程序中,或把结
果存储到外部存储系统(如HDFS)

转化操作和行动操作的区别在于Spark 计算RDD 的方式不同。虽然你可以在任何时候定
义新的RDD,但Spark 只会惰性计算这些RDD。它们只有第一次在一个行动操作中用到
时,才会真正计算。

Represents an immutable, partitioned collection of elements that can be operated on in parallel:表示不可变的,集合中的分区可以并行运行(rdd一旦生产不可变,可分区,并行计算的特点)

https://github.com/apache/spark/blob/master/core/src/main/scala/org/apache/spark/rdd/RDD.scala

 RDD的五个主要特点:

 A list of partitions  分区

A function for computing each split   一个函数应用于各个分区(并行计算)

A list of dependencies on other RDDs  依赖其他RDD        传递依赖  RDD1=>RDD2=>RDD3

Optionally(可选), a Partitioner for key-value RDDs (e.g. to say that the RDD is hash-partitioned)

Optionally, a list of preferred locations to compute each split on (e.g. block locations for an HDFS file)

 数据在哪个节点,task在哪个节点运行性能最好,不用在各个节点上进行数据传输

abstract class RDD[T: ClassTag](
@transient private var _sc: SparkContext,
@transient private var deps: Seq[Dependency[_]]
) extends Serializable with Logging {

}

说明rdd是抽象类,必然是子类实现

可序列化

T  泛型 支持各种数据类型

RDD的特点与源码的对应关系如下:

 def compute(split: Partition, context: TaskContext): Iterator[T]

(分区,每个task一个上下文) RDD的 第二个特点

在SPARK中,计算时,有多少个patition就对应多少个task来执行

protected def getPartitions: Array[Partition] 

RDD第一个特点

protected def getDependencies: Seq[Dependency[_]] = deps 

获取依赖关系 第三个特点

protected def getPreferredLocations(split: Partition): Seq[String] = Nil

第五个特点

RDD的操作大致分为4类

创建操作 如makeRDD

转换操作 如map

控制操作 如cache

行动操作 如collect

RDD的实现

作业调度

当对RDD执行转换操作时,调度器会根据RDD的血统来构建由若干调度阶段(Stage)组成的有向无环图(DAG),每个调度阶段包含尽可能多的连续窄依赖转换。调度器按照DAG顺序计算,并最终得到目标RDD。

调度器向各个节点分配任务采用延时调度机制并根据数据存储位置(数据本地性)来确定。若一个任务需要处理的某个分区刚好存储在某个节点的内存中,则该任务分配给该节点;如果在内存中不包含该分区,调度器会找到包含该RDD的较佳的位置,并把任务分配给所在节点。

spark如何计算作业调度调度阶段如下图所示:

 

对于执行失败的任务,只要它的对应调度阶段父类信息依然可以用,该任务会分散到其他阶段重新执行,如果某些调度阶段不可用,则重新提交相应的任务,并以并行方式计算丢失的分区。在作业中如果某个任务执行缓慢,系统则会在其他节点上执行该任务的副本,并取最先得到的结果作为最终结果.

解析器集成

内存管理

spark提供了三种持久化RDD的存储策略:未序列化java对象存在内存中,序列化的数据存于内存以及存储在磁盘中

第一个选项是最优的,因为可以直接访问在java虚拟机内存中的RDD对象;

空间有限的情况下,第二种方式可以让用户采用比java对象更有效的内存组织方式,但代价是降低了效率;

第三种策略适用于RDD太大的情形,每次重新计算改RDD会带来额外的资源开销(I/O)

对于内存使用LRU回收算法来进行管理,当计算得到一个新的RDD分区,但没有足够的空间存储时,系统会从最近最少使用的RDD回收其一个分区的空间。除非该RDD是新分区对应的RDD,这种情况下,spark会将旧的分区继续保留在内存中,防止同一个RDD的分区被循环调入/调出。

检查点支持

虽然血统可以用于错误后的RDD恢复,但对于很长血统的RDD,这样恢复会耗时比较长,因此需要通过检查点操作(checkpoint)来保存到外部存储中。

多用户管理

spark通用接口

spark的四类操作:创建,转换,控制,行为

Copyright © 2024 打杂滴
Powered by .NET 9.0 on Kubernetes