RDD的转换

  Spark会根据用户提交的计算逻辑中的RDD的转换和动作来生成RDD之间的依赖关系,同时这个计算链也就生成了逻辑上的DAG。接下来以“Word Count”为例,详细描述这个DAG生成的实现过程。

Spark Scala版本的Word Count程序如下:

1: val file = spark.textFile("hdfs://...")
2: val counts = file.flatMap(line => line.split(" "))
3:  .map(word => (word, 1))
4:  .reduceByKey(_ + _)
5: counts.saveAsTextFile("hdfs://...")

file和counts都是RDD,其中file是从HDFS上读取文件并创建了RDD,而counts是在file的基础上通过flatMap、map和reduceByKey这三个RDD转换生成的。最后,counts调用了动作saveAsTextFile,用户的计算逻辑就从这里开始提交的集群进行计算。那么上面这5行代码的具体实现是什么呢?

1)行1:spark是org.apache.spark.SparkContext的实例,它是用户程序和Spark的交互接口。spark会负责连接到集群管理者,并根据用户设置或者系统默认设置来申请计算资源,完成RDD的创建等。

  spark.textFile("hdfs://...")就完成了一个org.apache.spark.rdd.HadoopRDD的创建,并且完成了一次RDD的转换:通过map转换到一个org.apache.spark.rdd.MapPartitions-RDD。

  也就是说,file实际上是一个MapPartitionsRDD,它保存了文件的所有行的数据内容。

2)行2:将file中的所有行的内容,以空格分隔为单词的列表,然后将这个按照行构成的单词列表合并为一个列表。最后,以每个单词为元素的列表被保存到MapPartitionsRDD

3)行3:将第2步生成的MapPartitionsRDD再次经过map将每个单词word转为(word, 1)的元组。这些元组最终被放到一个MapPartitionsRDD中。

4)行4:首先会生成一个MapPartitionsRDD,起到map端combiner的作用;然后会生成一个ShuffledRDD,它从上一个RDD的输出读取数据,作为reducer的开始;最后,还会生成一个MapPartitionsRDD,起到reducer端reduce的作用。

5)行5:首先会生成一个MapPartitionsRDD,这个RDD会通过调用org.apache.spark.rdd.PairRDDFunctions#saveAsHadoopDataset向HDFS输出RDD的数据内容。最后,调用org.apache.spark.SparkContext#runJob向集群提交这个计算任务。

RDD之间的关系可以从两个维度来理解:一个是RDD是从哪些RDD转换而来,也就是RDD的parent RDD(s)是什么;还有就是依赖于parent RDD(s)的哪些Partition(s)。这个关系,就是RDD之间的依赖,org.apache.spark.Dependency。根据依赖于parent RDD(s)的Partitions的不同情况,Spark将这种依赖分为两种,一种是宽依赖,一种是窄依赖。

RDD的依赖关系(宽依赖和窄依赖)

如,假设,现在如下

所以,

比如,我这里是刚好是4台worker1、worker2、worker3、worker4。还有1台Master。

soga,

val file = spark.textFile("hdfs://...")

1)行1:spark是org.apache.spark.SparkContext的实例,它是用户程序和Spark的交互接口。spark会负责连接到集群管理者,并根据用户设置或者系统默认设置来申请计算资源,完成RDD的创建等。

  spark.textFile("hdfs://...")就完成了一个org.apache.spark.rdd.HadoopRDD的创建,并且完成了一次RDD的转换:通过map转换到一个org.apache.spark.rdd.MapPartitions-RDD。

  也就是说,file实际上是一个MapPartitionsRDD,它保存了文件的所有行的数据内容。

想要成为高手,一定要多看源码,看上几十遍都太少了,包括看上10个版本的源码。无论是hadoop、还是spark

val counts = file.flatMap(line => line.split(" ")) 2)行2:将file中的所有行的内容,以空格分隔为单词的列表,然后将这个按照行构成的单词列表合并为一个列表。最后,以每个单词为元素的列表被保存到MapPartitionsRDD

.map(word => (word, 1))    3)行3:将第2步生成的MapPartitionsRDD再次经过map将每个单词word转为(word, 1)的元组。这些元组最终被放到一个MapPartitionsRDD中。

至此,windows本地,已经完成了。

下面是在网络里了。

注意啦! 分区是计算概念,分片是数据概念。

有4台worker,每台都在自己内存计算。

.reduceByKey(_ + _)

4)行4:首先会生成一个MapPartitionsRDD,起到map端combiner的作用;然后会生成一个ShuffledRDD,它从上一个RDD的输出读取数据,作为reducer的开始;最后,还会生成一个MapPartitionsRDD,起到reducer端reduce的作用。

总结:

第一个stage :

HadoopRDD  ->   MapPartitionRDD  ->   MapPartitionsRDD  ->  MapPartitionsRDD  ->  MapPartitionsRDD

第二个stage :  

  Stage shuffledRDD   ->  MapPartitionsRDD

Spark RDD概念学习系列之RDD的转换(十)的更多相关文章

  1. Spark RDD概念学习系列之RDD的checkpoint(九)

     RDD的检查点 首先,要清楚.为什么spark要引入检查点机制?引入RDD的检查点?  答:如果缓存丢失了,则需要重新计算.如果计算特别复杂或者计算耗时特别多,那么缓存丢失对于整个Job的影响是不容 ...

  2. Spark RDD概念学习系列之RDD的缓存(八)

      RDD的缓存 RDD的缓存和RDD的checkpoint的区别 缓存是在计算结束后,直接将计算结果通过用户定义的存储级别(存储级别定义了缓存存储的介质,现在支持内存.本地文件系统和Tachyon) ...

  3. Spark RDD概念学习系列之RDD的操作(七)

    RDD的操作 RDD支持两种操作:转换和动作. 1)转换,即从现有的数据集创建一个新的数据集. 2)动作,即在数据集上进行计算后,返回一个值给Driver程序. 例如,map就是一种转换,它将数据集每 ...

  4. Spark RDD概念学习系列之RDD是什么?(四)

       RDD是什么? 通俗地理解,RDD可以被抽象地理解为一个大的数组(Array),但是这个数组是分布在集群上的.详细见  Spark的数据存储 Spark的核心数据模型是RDD,但RDD是个抽象类 ...

  5. Spark RDD概念学习系列之RDD的依赖关系(宽依赖和窄依赖)(三)

    RDD的依赖关系?   RDD和它依赖的parent RDD(s)的关系有两种不同的类型,即窄依赖(narrow dependency)和宽依赖(wide dependency). 1)窄依赖指的是每 ...

  6. Spark RDD概念学习系列之RDD的缺点(二)

        RDD的缺点? RDD是Spark最基本也是最根本的数据抽象,它具备像MapReduce等数据流模型的容错性,并且允许开发人员在大型集群上执行基于内存的计算. 为了有效地实现容错,(详细见ht ...

  7. Spark RDD概念学习系列之rdd的依赖关系彻底解密(十九)

    本期内容: 1.RDD依赖关系的本质内幕 2.依赖关系下的数据流视图 3.经典的RDD依赖关系解析 4.RDD依赖关系源码内幕 1.RDD依赖关系的本质内幕 由于RDD是粗粒度的操作数据集,每个Tra ...

  8. Spark RDD概念学习系列之RDD的创建(六)

    RDD的创建  两种方式来创建RDD: 1)由一个已经存在的Scala集合创建 2)由外部存储系统的数据集创建,包括本地文件系统,还有所有Hadoop支持的数据集,比如HDFS.Cassandra.H ...

  9. Spark RDD概念学习系列之RDD的5大特点(五)

      RDD的5大特点  1)有一个分片列表,就是能被切分,和Hadoop一样,能够切分的数据才能并行计算. 一组分片(partition),即数据集的基本组成单位,对于RDD来说,每个分片都会被一个计 ...

随机推荐

  1. 《OD学hadoop》第一周0626

    一.磁盘管理 Linux添加新硬盘.分区.格式化.自动挂载 http://lxsym.blog.51cto.com/1364623/321643 给Linux系统新增加一块硬盘 http://www. ...

  2. 在DirectX 中进行2D渲染

    http://flcstudio.blog.163.com/blog/static/756035392008115111123672/ 最近,我看到很多关于DirectX8在最新的API中摒弃Dire ...

  3. 聚集索引、非聚集索引、聚集索引组织表、堆组织表、Mysql/PostgreSQL对比、联合主键/自增长、InnoDB/MyISAM(引擎方面另开一篇)

    参考了多篇文章,分别记录,如下. 下面是第一篇的总结 http://www.jb51.net/article/76007.htm: 在MySQL中,InnoDB引擎表是(聚集)索引组织表(cluste ...

  4. UVa 10106 Product

    高精度乘法问题,WA了两次是因为没有考虑结果为0的情况.  Product  The Problem The problem is to multiply two integers X, Y. (0& ...

  5. 中文分词系列(一) 双数组Tire树(DART)详解

    1 双数组Tire树简介 双数组Tire树是Tire树的升级版,Tire取自英文Retrieval中的一部分,即检索树,又称作字典树或者键树.下面简单介绍一下Tire树. 1.1 Tire树 Trie ...

  6. phonegap 单例模式

    今天在使用云推送的时候  app打开着,然后 控制台推送一条消息 结果点击后又重新打开了一个客户端... ok,我需要的是单例,我使用了singleInstance  ,达到了效果. 引用百度知道的 ...

  7. linux 下RMAN备份shell脚本

    RMAN备份对于Oracle数据库的备份与恢复简单易用,成本低廉.对于使用非catalog方式而言,将RMAN脚本嵌入到shell脚本,然后再通过crontab来实现中小型数据库数据库备份无疑是首选. ...

  8. nginx的配置,要求根据不同的来路域名,发送到不同的端口去处理

    这一台电脑上既有tomcat 也有 apache,他俩是没有办法同时享用80端口的.我现在让tomcat用8088,apache用8080,然后让nginx用80,这样nginx在收到请求后,根据不同 ...

  9. [Java]获取图片高和宽

    通过javax.imageio.ImageIO类中的read()函数读取的图片,存放在类java.awt.image.BufferedImage类中.调用BufferedImage类中的getWidt ...

  10. MAC OSX 驱动操作

    mac ox系统的驱动安装常规操作:下载到 *.kext 的驱动以后,都可以直接把它拖到 /System/Library/Extensions/ 下替换掉原来的文件.替换了以后,还需要修复权限才能够正 ...