zoukankan      html  css  js  c++  java
  • RDD

    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的四类操作:创建,转换,控制,行为

  • 相关阅读:
    【design pattern】代理模式
    Java IO(十七)FIleReader 和 FileWriter
    Java IO(十六)InputStreamReader 和 InputStreamWriter
    Java IO(十五)FilterReader 和 FilterWriter、FilterReader 子类 PushBackReader
    Java IO(十四) CharArrayReader 和 CharArrayWriter
    Java IO(十三)PipedReader 和 PipedWriter
    Java IO(十二) 字符流 Writer 和 Reader
    Java IO(十一) DataInputStream 和 DataOutputStream
    Java IO(十) BufferedInputStream 和 BufferedOutputStream
    Java IO(九)FilterInputStream 和 FilterOutputStream
  • 原文地址:https://www.cnblogs.com/playforever/p/7792753.html
Copyright © 2011-2022 走看看