Spark内核:RDD基础

RDD产生的背景

MR程序

这里写图片描述

这里写图片描述

每个hadoop作业都是从物理存储上加载数据,然后操作数据进行运算,最后写入到物理存储设备中。

但是这样的话就无法复用曾经的计算结果或中间计算结果等。Hadoop每次作业多从磁盘上读写数据而且第二次作业的时候会再次从磁盘上读写数据。

MR对两种应用的处理并不是很高效,一个是因为需要大量迭代的算法(图计算和机器学习),另一个是交互式数据挖掘工具(重复采集一个数据子集)。基于这两种情况,如果能将数据保存在内存汇总就能够极大的提高性能。
同时,MR的位置感知,容错性,负载均衡等。容错性比较难以实现,我们一般的分布式数据集的容错有两种方式:数据检查点和记录数据更新
如果数据太大了,那么数据检查点的成本会非常高,它需要数据中心之间的高网络连接和机器之间的大量数据复制。但是实际情况是宽带不达标,存储大量消耗,这让数据容错面临一个新的挑战。

在这种背景下,RDD(Resilient Distributed Datasets, 弹性分布式数据集)诞生了


RDD程序
这里写图片描述

这里写图片描述


Spark拥有位置感知,容错,负载均衡等特征。
但是Spark为了更好的实现容错机制,RDD提供了一种高度受限的共享内存模型——只读模型(不可变)。这种模型是分区记录的集合,读操作细粒度到可以精确到每一条数据,但是写操作确实粗粒度的(批量)。

可以说,RDD就是Spark核心的通用的抽象数据结构。
通过RDD,用户可以对程序运行中间结果进行显式的命名和物化,可以控制其分区,可以指定执行的特定步骤。(MR是循环执行)。
Spark通过RDD之间的依赖关系和高度抽象,让编程模型更易用,容错性也更好。一些大量迭代算法或者多次使用中间数据的查询,都是RDD特别适合的场景。


RDD基础

RDD(Resilient Distributed Datasets, 弹性分布式数据集),分布式内存的一个抽象概念,一种高度受限的共享内存模型,即RDD是只读的记录分区的集合,能横跨集群所有节点进行并行计算,是一种基于工作集的应用抽象。

这里写图片描述

每个RDD的数据都以Block的形式存储与多要基础上。如上图,每个Executor会启动一个BlockManagerSlave,并管理一部分的Block,而Block的元数据由Driver节点上的BlockManagerMaster保存,BlockManagerSlave生成Block后会向BlockManagerMaster注册该Block,BlockManagerMaster管理RDD和Block之间的关系,当RDD不在需要存储的时候,将向BlockManagerSlave发送指令删除相应的BLock。


RDD的五大特性

-(个人理解)

  1. 分区列表(a list of partitions)
    Spark RDD 是被分区的,每一个都会被一个计算任务(Task)处理,分区数决定并行计算数量,RDD的并行度默认从父RDD传给子RDD。默认情况下一个HDFS上的数据分片就是一个partition,RDD分片数据决定了并行计算的力度,可以在创建RDD时指定RDD分片个数,如果不指定分区数量,当RDD从集合创建的时候,会使用该程序分配到的资源,如果是HDFS,则默认为文件的Block数量。

  2. 每个分区都有一个计算函数(a function for computing each split)
    每个分区都会有计算函数,Spark的RDD的计算函数是一分片为基本单位的,每个RDD都会实现compute函数,对具体的分片进行计算,RDD中的分片是并行的,所以分布式并行计算,有一点很重要,就是由于RDD有前后依赖关系,遇到宽依赖关系,例如ReduceByKey等操作的时候划分为Stage,Stage内部的操作都是通过Pipeline,在具体处理数据的时候会通过BlockManager来获取相关数据。

  3. 依赖其他RDD的列表(a list of dependecies on other RDDs)
    RDD的依赖关系,由于RDD每次转换都会生成新的RDD,所以RDD会形成类似流水线一样的前后依赖关系,当然宽依赖关系就不类似流水线

  4. Key-Value数据类型的RDD可以设置分区器(Optionally,a Partitioner for key-value RDDs),控制分区策略和分区数
    每个key-value形式的RDD都有Partition属性,它决定了RDD如何分区。当然Partition的个数还决定了Stage的Task个数。RDD的分片函数,想控制RDD的分片函数的时候可以分区,传入相关的参数,例如HashPartitioner,RangePartition,其本身就是针对key-value的形式,如果不是key-value的形式,他就不会具有具体的patitioner。
    分区本身决定了下一步会产生多少并行的分片,同时也决定了当前并行shuffle输出的并行数据。

  5. 每个分区都有一个优先位置列表(optionally, a list preferred locations to compute each split on)
    这个会存储每个Partition的有限位置,对于一个HDFS文件来说就是每个Partition块的位置。
    这就是所谓的数据不动代码动


RDD的一些其他特性

1、动态进行内存和磁盘数据存储的切换

Spark优先会把数据放到内存中,如果内存实在放不下,会放到磁盘里面,这样就能计算超出内存大小的数据了。当然,这样就要考虑数据的放置策略以及优化策略。当程序内存不足的时候,Spark应用程序将数据自动从内存存储切换到磁盘存储,一保证其高效的运行。

2、基于Lineage的高效容错机制

Lineage是基于Spark RDD的依赖关系来完成的(宽依赖,窄依赖),这种依赖便于恢复失去的数据。
每个操作只关联其副操作,每个分片的数据之间互不影响,出现错误只需要恢复单个split的特定部分就行了。
一般来说,常规容错方式有两种,一个是数据检查点,一个是记录数据的更新。
设置数据检查点,就是通过数据中心的网络连接不同的机器,然后每次操作都会复制数据集,就相当于每次都有一个拷贝,拷贝是通过网络的,因此网络带宽就是限制其效率的瓶颈,同时也会对存储资源有很大的消耗。

3、Task失败后会进行一定次数的重启

默认的配置中,重新尝试的次数是4次
TaskSchedulerImpl是底层的任务调度接口TaskScheduler的实现,这些scheduler从每个Stage中的DAGScheduler中获取TaskSet,然后运行,尝试是否有故障。
DAGScheduler是高层调度,它计算每个Job的Stages的DAG,然后提交stages用TaskSet的形式启动TaskScheduler调度。

4、Stage如果失败也会进行一定次数的重试

这个的默认设置也是4次。
这种重试可以直接计算失败的阶段,只用计算失败的数据分片。Stage是Spark Job运行时具有相同逻辑功能且并行计算任务的一个基本单元。
Stage中所有的任务都依赖同样的shuffle,每个DAG任务都通过DAGScheduler在stage的边界处发生shuffle形成stage,然后DAGScheduler按照这些阶段的拓扑顺序运行。
(ShuffleMapStage、ResultStage。ShuffleMapStage是DAG产生数据进行shuffle的中间阶段,它发生在每次shuffle操作之前,可能包含多个pipelined操作,ResultStage阶段捕获函数在RDD的分区上进行Action算子计算结果,有些Stage 不是运行在RDD的所有分区上)

5、checkpoint和persist可以主动或者被动出发

我们可以利用不同的存储级别来存储每一个被持久化的RDD。例如,它允许持久化集合到磁盘上,将集合作为序列化的java对象持久化到内存汇总,在节点间复制结合或者存储集合到Tachyon中,可以通过传递一个StorageLevel对象给persist()方法设置这些存储级别,cache()方法使用来默认存储级别。

6、任务调度的弹性。

Spark将执行模型抽象为通用的抽象无环图(DAG),这样可以将多个Stage的任务串联或并行执行,从不需要将Stage中间结果输出到HDFS中,当发生节点运行故障时可以有其他节点代替该故障节点继续运行。

7、数据分片数据的高度弹性

Spark进行数据分片时,默认将数据放在内存中如果内存放不下,一部分放在磁盘中。如果每个Partition的数据Block比较大,这个时候需要考虑吧Partition编程更小的数据分片,这样让Spark处理更多的批次但是不会出现OOM(Object-Oriented Method)


RDD功能

RDD有三种创建方式:

  1. 将一个程序内存中构建的集合分布式分发到集群上
  2. 从磁盘上的数据集生成
  3. 从一个现存的RDD生成

RDD支持的文件类型:

  1. Text Files
  2. Sequence Files
  3. Hadoop Input Format

    通过已经存在的Scala集合创建RDD
    通过HDFS、本地文件系统创建RDD


基础就到这里



如果有任何意见或者建议,请联系我,谢谢

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
1. RDD(Resilient Distributed Datasets):弹性分布式数据集,是Spark中最基本的数据抽象,是一个不可变的分布式对象集合,可以并行计算。RDD可以通过从Hadoop InputFormat中读取数据、在Spark中的其他RDD转换操作和从外部存储系统中获取数据创建。 2. DAG(Directed Acyclic Graph):有向无环图,它表示Spark任务执行的依赖关系。每个Spark应用程序都会生成一个DAG,用于描述任务之间的依赖关系。 3. Executor:执行器,是Spark中执行计算任务的工作进程。一个Spark应用程序可以由多个Executor组成,每个Executor都运行在独立的JVM进程中,负责运行Spark应用程序中的任务。 4. Application:Spark应用程序,是一个包含了用户编写的Spark任务代码和Spark集群上的资源配置信息的集合。在Spark中,应用程序通常以JAR包的形式提交到Spark集群中运行。 5. Task:任务,是Spark应用程序中最小的计算单元,是对RDD的一个分区进行操作的一段代码。每个Task都会被分配到一个Executor上运行。 6. Job:作业,是由一组相关的Task组成的,这些Task可以并行执行,且它们之间存在依赖关系。Spark应用程序中的每个Action操作都会生成一个Job。 7. Stage:阶段,是Spark作业中的一个任务划分单元,是由若干个Task组成的。Spark会将一个Job划分成多个Stage,以便进行并行计算。一个Stage中的所有Task都可以并行执行,但是它们之间存在着依赖关系。Spark将具有相同的计算依赖关系的Task划分为同一个Stage。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值