赞
踩
书籍是最好的朋友。当生活中遇到任何困难的时候,你都能够向它求助,它永远不会背弃你。
传统的MapReduce虽然具有自动容错、平衡负载和可拓展性的优点,但是其最大缺点是采用非循环式的数据流模型,使得在迭代计算式要进行大量的磁盘IO操作。Spark中的RDD可以很好的解决这一缺点。
RDD是Spark提供的最重要的抽象概念,我们可以将RDD理解为一个分布式存储在集群中的大型数据集合,不同RDD之间可以通过转换操作形成依赖关系实现管道化,从而避免了中间结果的I/O操作,提高数据处理的速度和性能。接下来,本章将针对RDD进行详细讲解。
需要注意的是,RDD的分区函数是针对(Key,Value)类型的RDD,分区函数根据Key对RDD元素进行分区。因此,当需要对一些非(Key,Value)类型的RDD进行自定义分区时,需要先把RDD元素转换为(Key,Value)类型,再通过分区函数进行分区操作。
如果想要实现自定义分区,就需要定义一个类,使得这个自定义的类继承org.apache.spark.Partitioner类,并实现其中的3个方法,具体如下:
def numPartitions:Int
def getPartition(Key:Any)
equals(other:Any)
RDD做map、filter和union算子操作时,是属于窄依赖的第一类表现;而RDD做join算子操作(对输入进行协同划分)时,是属于窄依赖表现的第二类。输入协同划分是指多个父RDD的某一个分区的所有Key,被划分到子RDD的同一分区。当子RDD做算子操作,因为某个分区操作失败导致数据丢失时,只需要重新对父RDD中对应的分区做算子操作即可恢复数据。当RDD执行map、filter及union和join操作时,都会产生窄依赖。如下图所示
为了便于理解,我们通常把宽依赖形象的比喻为超生。当RDD做groupByKey和join操作时,会产生宽依赖,如下图所示。
父RDD做groupByKey和join(输入未协同划分)算子操作时,子RDD的每一个分区都会依赖于所有父RDD的所有分区。当子RDD做算子操作,因为某个分区操作失败导致数据丢失时,则需要重新对父RDD中的所有分区进行算子操作才能恢复数据。
需要注意的是,join算子操作既可以属于窄依赖,也可以属于宽依赖。当join算子操作后,分区数量没有变化则为窄依赖(如join with inputs co-partitioned,输入协同划分)﹔当join算子操作后,分区数量发生变化则为宽依赖(如join with inputs not co-partitioned,输入非协同划分)。
RDD(弹性分布式数据集)是Spark中最基本的数据抽象。它将数据分布在集群的多个节点上进行并行处理,具有容错性和高效性。
RDD的分区是将一个大的数据集划分为多个小的数据块,每个分区都存储在集群的不同节点上,并行进行处理。通过对RDD进行分区,可以实现数据的并行计算和更高的效率。
RDD的依赖关系是指RDD之间的依赖关系图,用于记录RDD之间的血缘关系。当对一个RDD进行转换操作时,会生成一个新的RDD,并且新的RDD会记录对原始RDD的依赖关系。依赖关系分为窄依赖和宽依赖,窄依赖表示每个父RDD的分区最多只被一个子RDD的分区使用,宽依赖表示每个父RDD的分区可以被多个子RDD的分区使用。
通过对RDD的分区和依赖关系的管理,Spark可以实现数据的高效并行处理和容错。同时,由于RDD的不可变性,使得Spark可以通过血缘关系进行数据的恢复和重算,提高了计算的容错性和可靠性。
转载自:https://blog.csdn.net/u014727709/article/details/136033042
欢迎
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。