spark:RDD的五大特性

1.A list of partitions

RDD是一个由多个partition(某个节点里的某一片连续的数据)组成的的list;将数据加载为RDD时,一般会遵循数据的本地性(一般一个hdfs里的block会加载为一个partition)。

2.A function for computing each split

一个函数计算每一个分片,RDD的每个partition上面都会有function,也就是函数应用,其作用是实现RDD之间partition的转换。

3.A list of dependencies on other RDDs

RDD会记录它的依赖 ,依赖还具体分为宽依赖和窄依赖,但并不是所有的RDD都有依赖。为了容错(重算,cache,checkpoint),也就是说在内存中的RDD操作时出错或丢失会进行重算。

4.Optionally,a Partitioner for Key-value RDDs

  可选项,如果RDD里面存的数据是key-value形式,则可以传递一个自定义的Partitioner进行重新分区,例如这里自定义的Partitioner是基于key进行分区,那则会将不同RDD里面的相同key的数据放到同一个partition里面

5.Optionally, a list of preferred locations to compute each split on

最优的位置去计算,也就是数据的本地性。

https://blog.csdn.net/zym1117/article/details/79532458

详细:

Spark RDD五大特性

RDD源码观看

1,分区列表( a list of partitions)

Spark RDD是被分区的,每一个分区都会被一个计算任务(Task)处理,分区数决定了并行计算的数量,RDD的并行度默认从父RDD传给子RDD。默认情况下,一个HDFS上的数据分片就是一个 partiton,RDD分片数决定了并行计算的力度,可以在创建RDD时指定RDD分片个数(分区)。

如果不指定分区数量,当RDD从集合创建时,则默认分区数量为该程序所分配到的资源的CPU核数(每个Core可以承载2~4个 partition),如果是从HDFS文件创建,默认为文件的 Block数。

2,每一个分区(分片)都有一个计算函数( a function for computing each split)

每个分区都会有计算函数, Spark的RDD的计算函数是以分片为基本单位的,每个RDD都会实现 compute函数,对具体的分片进行计算,RDD中的分片是并行的,所以是分布式并行计算。

有一点非常重要,就是由于RDD有前后依赖关系,遇到宽依赖关系,如reduce By Key等这些操作时划分成 Stage, Stage内部的操作都是通过 Pipeline进行的,在具体处理数据时它会通过 Blockmanager来获取相关的数据,因为具体的 split要从外界读数据,也要把具体的计算结果写入外界,所以用了一个管理器,具体的 split都会映射成 BlockManager的Block,而具体的splt会被函数处理,函数处理的具体形式是以任务的形式进行的。

3,依赖于其他RDD的列表( a list of dependencies on other RDDS)

由于RDD每次转换都会生成新的RDD,所以RDD会形成类似流水线一样的前后依赖关系,当然宽依赖就不类似于流水线了,宽依赖后面的RDD具体的数据分片会依赖前面所有的RDD的所有数据分片,这个时候数据分片就不进行内存中的 Pipeline,一般都是跨机器的,因为有前后的依赖关系,所以当有分区的数据丢失时, Spark会通过依赖关系进行重新计算,从而计算出丢失的数据,而不是对RDD所有的分区进行重新计算。

RDD之间的依赖有两种:窄依赖( Narrow Dependency)和宽依赖( Wide Dependency)。

RDD是 Spark的核心数据结构,通过RDD的依赖关系形成调度关系。通过对RDD的操作形成整个 Spark程序。

窄依赖指的是每一个 parent RDD的 Partition最多被 child rdd的一个 Partition所使用。

宽依赖指的是多个 child RDD的Partion会依赖于同一个 parent RDD的 Partition。

可以从两个方面来理解RDD之间的依赖关系,一方面是RDD的 parent RDD是什么(上图左边的RDD),另一方面是依赖于 parent RDD的哪些 Partion;根据依赖于 parent RDD的哪些 Partion的不同情况, Spark将 Dependency分为宽依赖和窄依赖两种。

Spak中的宽依赖指的是生成的RDD的每一个 partition都依赖于父RDD所有的 partition。

宽依赖典型的操作有 group by key, sort by key等,宽依赖意味着Shuffle操作,这是 Spark划分Stage的边界的依据。

Spark中的宽依赖支持两种 Shuffle Manager,即 Hash Shufflemanager和 Sort shufflemanager,前者是基于Hash的 Shuffle机制,后者是基于排序的 Shuffle机制。

4,key- value数据类型的RDD分区器( a Partitioner for key- alue RDDS)、控制分区策略和分区数

每个key- value形式的RDD都有 Partitioner属性,它决定了RDD如何分区。

当然,Partiton的个数还决定了每个Stage的Task个数。

RDD的分片函数可以分区( Partitioner),可传入相关的参数,如 Hash Partitioner和 Range Partitioner,它本身针对key- value的形式,如果不是key-value的形式它就不会有具体的 Partitioner, Partitioner本身决定了下一步会产生多少并行的分片,同时它本身也决定了当前并行( Parallelize) Shuffle输出的并行数据,从而使Spark具有能够控制数据在不同结点上分区的特性,用户可以自定义分区策略,如Hash分区等。

spark提供了 partition By运算符,能通过集群对RDD进行数据再分配来创建一个新的RDD。

5,每个分区都有一个优先位置列表( a list of preferred locations to compute each split on)

优先位置列表会存储每个 Partition的优先位置,对于一个HDFS文件来说,就是每个Partition块的位置。

观察运行 Spark集群的控制台就会发现,Spark在具体计算、具体分片以前,它已经清楚地知道任务发生在哪个结点上,也就是说任务本身是计算层面的、代码层面的,代码发生运算之前它就已经知道它要运算的数据在什么地方,有具体结点的信息。

这就符合大数据中数据不动代码动的原则,即“移动数据不如移动计算”的理念。数据不动代码动的最高境界是数据就在当前结点的内存中。这时候有可能是 Memory级别或 Tachyon级别的,Spark本身在进行任务调度时会尽可能地将任务分配到处理数据的数据块所在的具体位置。

 Scala源代码函数get Parferredlocations可知,每次计算都符合完美的数据本地性。可在RDD类源代码文件中找到4个方法和1个属性,对应上述所阐述的RDD的五大特性,源代码剪辑如下

原文参考:http://m.sohu.com/a/229461623_100147700

猜你喜欢

转载自blog.csdn.net/weixin_38750084/article/details/82955062