RDD深入讲解

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

1.什么是RDD:

RDD(Resilient Distributed Dataset)弹性分布式数据集

  • 弹性:在分布式计算的时候可以容错,比如某个节点挂了,或者某个部分的数据丢失了,可以通过RDD的机制进行修复
  • 分布式:数据归属在大的集群上,可以拆成多份存储在各个节点上运行,这样才能体现分布式计算框架的价值所在,因为他们之间并没有依赖关系
  • 数据集:可以通过读取一个文件或者通过编程的方式来创建一个数据集,也可以通过一个数据的转换来得到一个新的数据集(后面会详细讲RDD的三种创建方式),这个数据集可以被拆分成多个分区来进行计算;类似HDFS上以block为单位,拆分成多个block进行存储。

RDD是Spark中最基本的数据抽象单元,可以大大降低开发者开发分布式应用程序的门槛并提高执行效率;spark core是基于RDD进行编程的;spark streaming 是基于DStream进行编程的;spark SQL是借助于HiveContext来编程的;
RDD代表着一种不可变的集合,集合里的所有元素可以被分区,这些被拆分成的每一部分可以通过并行的方式进行操作。

例如:

RDDA:(1,2,3,4,5,6,7,8,9)
hadoop000:Partition1:(1,2,3)
hadoop001:Partition2:(4,5,6)
hadoop002:Partition3:(7,8,9)
RDDA被拆分成了三个分区,RDD是由多个Partition所构成的,对RDD中的每个元素进行操作实际上就是对hadoop000、hadoop001、hadoop002三台机器上的Partition1、Partition2、Partition3进行操作

2.RDD的定义:

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

解释:

1)抽象类(说明不能直接使用),我们直接使用其子类即可
2)可序列化Serializable ,可存储各类数据
3)Logging  记录日志
4)T 泛型,支持各种数据类型(Spark程序的编译以及运行是区分了Driver和Executor的,只有在运行的时候才知道完整的信息)
5)SparkContext   
6)@transient

3.RDD的五大特性:

1) A list of partitions 
RDD是由分区组成的,有一系列Partition构成
2) A function for computing each split
对于计算,一个函数是作用于每个分片上的,并行计算
3) A list of dependencies on other RDDs
依赖关系   (加载)RDDA==>RDDB==>RDDC==>RDDD,RDDD是会依赖于前面的,从RDDA加载进来,然后转换变成了RDDB,那么RDDA里的每个Partition就变成了RDDB里的Partition,他们之间会有依赖关系,如果RDDA里的某个与元素或者分区挂了,那重新加载一下就可以了;当然这里还会提到一,就是如果是窄依赖的话,如果RDDB里的某个元素或者分区挂了,那也可以用RDDA重新转换一下,同样的RDD中任一分区数据丢失了,Spark可以通过这个依赖关系重新计算分区里的数据,而不需要计算所有分区,这也体现了一个弹性,后面会对宽依赖以及窄依赖会详细介绍
4) Optionally, a Partitioner for key-value RDDs (e.g. to say that the RDD is hash-partitioned)
(a list of preferred locations:数据最好在哪台机器上运行),可对key-value的RDDS做分区,默认是hash分区,当然也可以指定一个Partition及逆行分区,常用的有hash,range
5)Optionally, a list of preferred locations to compute each split on (e.g. block locations for an HDFS file)
可选,在对每个分区进行计算的时候,可以选择在哪台机器上执行、计算最好;数据本地性,这样可以提升性能,因为没有移动的数据

spark中的所有调度和执行都是基于这些方法完成的,允许每个RDD实现自己的计算方式,实际上,用户可以通过重写这些函数来实现自定义的RDD。

4.五大特征在源码中的体现:

1)def compute(split: Partition, context: TaskContext): Iterator[T]
对RDD做计算就是对分区做计算(体现第二点)
2)protected def getPartitions: Array[Partition]
一个数组、一个集合类型是Partition(体现的是第一点)
3)  protected def getDependencies: Seq[Dependency[_]] = deps()
RDD之间有对应关系,有转换,有依赖(体现第三点)
4)protected def getPreferredLocations(split: Partition): Seq[String] = Nil
传进来split,返回的是一个数组,返回最合适的路径(体现第五大特点)
5)@transient val partitioner: Option[Partitioner] = None
对应KV,指定如何分区(体现第四大特点)

5.图解RDD:

在这里插入图片描述
解释:
假定现在有个RDD,它有五个partition,分布在三个节点之上。
RDD是可以做cache操作的,它有可能存在磁盘上,也有可能存在内存里,也有可能两个都有,也有可能存在多个副本。
现在有五个partition,如果取做某个计算时,就必然有五个task。如果core够用的话,就必然是五个task并行的去计算,如果不够的话,就先跑一轮,跑完再继续。
对于partition1来说,你去执行一个计算,肯定优先在NODE1节点上执行性能更好,如果在NODE2节点上执行,需要先把partition1的数据传输到NODE2上,再进行执行计算。
在Spark中,计算时,有多少partition就对应多少个task来执行

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值