Spark之初识RDD

RDD是什么

RDD是弹性的分布式数据集,一个RDD就是一个分布式对象集合,本质上是一个只读的分区记录集合,每个RDD可以分成多个分区,每个分区就是一个数据集片段,并且一个RDD的不同分区可以被保存到集群中不同的节点上,从而可以在集群中的不同节点上进行并行计算。

上面说得可能有点晦涩,一句话, RDD就是一个数据集合。

但是这个数据集合有一些特点:

  1. 分区的(partition):由于数据量太大,这个数据集不是存储在一个电脑里面,而是存储在集群中;
  2. 弹性(resilient): Spark把多个RDD的依赖关系组合成一张DAG图,当某一个RDD数据出错时,能够非常方便地从DAG图推断回来还原数据,RDD有非常强大的容错机制,这就是所谓的弹性;
  3. 不可变(Immutable): 也就是这个数据集合不能改变,对RDD的每一步转换操作,都生成一个新的RDD;

RDD提供了一组丰富的操作以支持常见的数据运算,分为“转换”和“行动”,转换操作接受RDD并返回RDD,行动操作接受RDD但返回非RDD(即输出一个值或结果)。

RDD典型的执行过程如下:

  1. RDD读入外部数据源(或者内存中的集合)进行创建;
  2. RDD经过一系列的“转换”操作,每一次都会产生不同的RDD,供给下一个“转换”使用;
  3. 最后一个RDD经“行动”操作进行处理,并输出到外部数据源(或者变成Scala集合或标量);

要注意的是:RDD采用了惰性调用,即在RDD的执行过程中,真正的计算发生在RDD的“行动”操作,对于“行动”之前的所有“转换”操作,Spark只是记录下“转换”操作应用的一些基础数据集以及RDD生成的轨迹,而不会触发真正的计算。

关于RDD的各种“转换”和“行动”操作的具体API,可以见Spark常用算子详解,总结得非常详细。

RDD间的依赖关系

RDD中不同的操作会使得不同RDD中的分区会产生不同的依赖。RDD中的依赖关系分为窄依赖与宽依赖。

总体而言,如果父RDD的一个分区只被一个子RDD的一个分区所使用就是窄依赖,否则就是宽依赖。窄依赖典型的操作包括map、filter、union等,宽依赖典型的操作包括groupByKey、sortByKey等。

相对而言,在两种依赖关系中,窄依赖的失败恢复更为高效,它只需要根据父RDD分区重新计算丢失的分区即可(不需要重新计算所有分区),而对于宽依赖而言,单个节点失效通常意味着重新计算过程会涉及多个父RDD分区,开销较大。

RDD运行过程

这里总结一下RDD在Spark架构中的运行过程

  1. 创建RDD对象;
  2. SparkContext负责计算RDD之间的依赖关系,构建DAG;
  3. DAGScheduler负责把DAG图分解成多个阶段,每个阶段中包含了多个任务,每个任务会被任务调度器分发给各个工作节点(Worker Node)上的Executor去执行;
原创文章 28 获赞 18 访问量 1万+

猜你喜欢

转载自blog.csdn.net/atuo200/article/details/105655962