RDD工作原理详解

一、Spark概念总结简要说明:

每个Spark应用都由一个驱动器程序(driver program)来发起集群上的各种 并行操作。
驱动器程序包含应用的 main 函数,
并且定义了集群上的分布式数据集,还对这 些分布式数据集应用了相关操作。
驱动器程序通过一个 SparkContext 对象来访问 Spark。这个对象代表对计算集群的
一个连 接。shell 启动时已经自动创建了一个 SparkContext 对象,是一个叫作 sc 的变量。
驱动器程序一般要管理多个执行器(executor)节点。

二、RDD到底是啥?竟然这么强大?
RDD是Spark的核心概念,是弹性分布式数据集(Resilient Distributed Dataset)的缩写。

MapReduce针对输入数据,将计算过程分为两个阶段:一个Map阶段,一个Reduce阶段,
可以理解为是面向过程的大数据计算。
我们在用MapReduce编程的时候,思考的是,如何将计算逻辑用Map和Reduce两个阶段实现,
map和reduce函数的输入和输出是什么,这也是我们在学习MapReduce编程时反复强调的。

而Spark则直接针对数据进行编程,将大规模数据集合抽象成一个RDD对象,一个RDD对象对应
一个物理上的数据集,然后在这个RDD上进行各种计算处理,得到一个新的RDD,继续计算处理,
直到得到最终想要的结果。
所以Spark可以理解为面向对象的大数据计算。
我们在进行Spark编程的时候,思考的是一个RDD对象需要经过什么样的操作,转换成
另一个RDD对象,思考的重心和落脚点都在RDD上。

三、RDD其实就是一个对象
所以在RDD上定义的函数分两种:转化函数和行动函数。

转化(transformation)函数:返回一个新的 RDD,比如 map() 和 filter()

执行(action)函数:把结果输出,不返回RDD。比如 saveAsTextFile、count() 和 first()。

跟MapReduce一样,Spark也是对大数据进行分片计算,Spark分布式计算的数据分片、
任务调度都是以RDD为单位展开的。

RDD上的转换操作又分为两种,一种转换操作产生的RDD不会出现新的分片,比如map、filter等,
也就是说一个RDD数据分片,经过map转换操作后,结果还在当前分片中。就像你用map函数对每
个数据加1,得到的还是这样一组数据,只是值不同。实际上,Spark并不是按照代码写的操作
顺序去生成RDD,比如map并不会在物理上生成一个新的数据集。物理上,Spark只有在产生新的
RDD分片时候,才会真的生成一个数据集,Spark的这种特性也被称为惰性计算。

另一种转换操作产生的RDD则会产生新的分片,比如reduceByKey,来自不同分片的相同Key
必须聚合在一起进行操作,这样就会产生新的RDD分片。
总之,Spark应用程序代码中的RDD和Spark执行过程中生成的物理RDD不是一一对应的,
RDD在Spark里面是一个非常灵活的概念,同时又非常重要,需要认真理解。

四、RDD 详细介绍

  1. 一组分片(Partition):即数据集的基本组成单位。对于RDD来说,每个分片都会被一个
    计算任务处理,并决定并行计算的粒度。用户可以在创建RDD时指定RDD的分片个数,如果没有指定,
    那么就会采用默认值。默认值是根据spark集群中分配的core的数量来决定。

  2. 一个计算每个分区的函数:Spark中RDD的计算是以分片为单位的,每个RDD都会实现compute
    函数以达到这个目的。compute函数会对迭代器进行复合,不需要保存每次计算的结果。

  3. RDD之间的依赖关系:RDD的每次转换都会生成一个新的RDD,所以RDD之间就会形成类似于
    流水线一样的前后依赖关系。在部分分区数据丢失时,Spark可以通过这个依赖关系重新计算
    丢失的分区数据,而不是对RDD的所有分区进行重新计算。

  4. 一个Partitioner:即RDD的分片函数。Partitioner函数决定了数据是如何进行分区的。

  5. 一个列表,存储每个Partition的优先位置(preferred location)。对于一个
    HDFS文件来说,这个列表保存的就是每个Partition所在的块的位置。按照“移动数据
    不如移动计算”的理念,Spark在进行任务调度的时候,会尽可能地将计算任务分配到其
    所要处理数据块的存储位置。

小结:RDD是一个应用层面的逻辑概念。一个RDD多个分片。RDD就是一个元数据记录集,
记录了RDD内存所有的关系数据。

五、RDD的依赖关系
由于RDD是粗粒度的操作数据集,每个转换操作都会生成一个新的RDD,所以RDD之间就会
形成类似流水线的前后依赖关系;RDD和它依赖的父RDD(s)的关系有两种不同的类型,
即窄依赖(narrow dependency)和宽依赖(wide dependency)。

窄依赖:是指每个父RDD的一个Partition最多被子RDD的一个Partition所使用,
例如map、filter等操作都会产生窄依赖(独生子女)
在窄依赖中,子RDD所依赖的父RDD的partition的个数是确定的。

宽依赖:是指一个父RDD的Partition会被多个子RDD的Partition所使用,例如groupByKey、
reduceByKey、sortByKey等操作都会产生宽依赖;(超生)也就是说,
只要产生了shuffle,就会产生宽依赖
而宽依赖是shuffle级别的,数据量越大,那么子RDD所依赖的父RDD的个数就越多,
从而子RDD所依赖的父RDD的partition的个数也会变得越来越多。

六、stage、DAG、task
Spark通过分析各个RDD的依赖关系生成了DAG(这里提到DAG了,划重点!),
即:Directed Acyclic Graph(有向无环图)
什么是DAG?
DAG,有向无环图,Directed Acyclic Graph的缩写,常用于建模。
Spark中使用DAG对RDD的关系进行建模,描述了RDD的依赖关系。
具体来说,DAG就是两部分的组合:
·所有的RDD
·对RDD的所有操作

划分阶段(stage):
通过分析各个 RDD 中分区之间的依赖关系 来决定如何划分阶段。

具体划分方法是:
在DAG中从后往前推,遇到宽依赖就断开,划分为一个stage;遇到窄依赖就将当前的RDD加入
到当前的stage中;窄依赖可以形成一个流水线操作,这样流水线执行大大提高了计算的效率。

对于窄依赖,由于partition依赖关系的确定性,partition的转换处理就可以在同一个线程里完成;
而对于宽依赖,只能等父RDD shuffle处理完成后,下一个stage才能开始接下来的计算。

Task:
task是stage里的一个任务执行单元,一般来说,一个RDD有多少个partition,就会有多少个task,
因为每一个task只是处理一个partition上的数据。
在spark中,Task的类型分为2种:ShuffleMapTask和ResultTask;
简单来说,DAG的最后一个阶段会为每个结果的partition生成一个ResultTask,而其余所有阶段都
会生成ShuffleMapTask。
之所以称之为ShuffleMapTask是因为它需要将自己的计算结果shuffle到下一个stage中。

DAG 解决了什么问题?
DAG 的出现主要是为了解决 Hadoop MapReduce 框架的局限性。那么 MapReduce 有什么局限性呢?
主要有两个:
1、每个 MapReduce 操作都是相互独立的,HADOOP不知道接下来会有哪些Map Reduce。
每一步的输出结果,都会持久化到硬盘或者 HDFS 上。如果在某些迭代的场景下,MapReduce 框架会
对硬盘和 HDFS 的读写造成大量浪费。
2、每一步都是堵塞在上一步中,所以当我们处理复杂计算时,会需要很长时间。

所以 Spark 中引入了 DAG,他解决了MapReduce的两个问题:
1、对于相同的stage,不需要把中间数据持久化到磁盘,数据是放到内存中进行快速迭代。
2、可以并行的执行不同的stage,不同stage之间相互没有影响

七、 RDD的弹性理解

  1. 自动进行内存和磁盘数据存储的切换
    Spark优先把数据放到内存中,如果内存放不下,就会放到磁盘里面,程序进行自动的存储切换。
  2. 基于血统的高效容错机制
    在RDD进行转换和动作的时候,会形成RDD的Lineage依赖链,当某一个RDD失效的时候,可以通过重新计算上游的RDD来重新生成丢失的RDD数据。
  3. Task如果失败会自动进行特定次数的重试
    RDD的计算任务如果运行失败,会自动进行任务的重新计算,默认次数是4次。
  4. Stage如果失败会自动进行特定次数的重试
    如果Job的某个Stage阶段计算失败,框架也会自动进行任务的重新计算,默认次数也是4次。
  5. Checkpoint和Persist可主动或被动触发
    RDD可以通过Persist持久化将RDD缓存到内存或者磁盘,当再次用到该RDD时直接读取就行。也可以将RDD进行检查点,检查点会将数据存储在HDFS中,该RDD的所有父RDD依赖都会被移除。
  6. 数据调度弹性
    Spark把整个Job执行模型抽象为通用的有向无环图DAG,可以将多Stage的任务串联或并行执行,调度引擎自动处理Stage的失败以及Task的失败。
  7. 数据分片的高度弹性
    可以根据业务的特征,动态调整数据分片的个数,提升整体的应用执行效率。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值