• 第2章 RDD编程(2.1-2.2)


    2RDD编程

    2.1 编程模型

    Spark中,RDD被表示为对象,通过对象上的方法调用来对RDD进行转换。经过一系列的transformations定义RDD之后,就可以调用actions触发RDD的计算,action可以是向应用程序返回结果(count, collect),或者是向存储系统保存数据(saveAsTextFile)。在Spark中,只有遇到action,才会执行RDD的计算(即延迟计算),这样在运行时可以通过管道的方式传输多个转换。

        要使用Spark,开发者需要编写一个Driver程序,它被提交到集群以调度运行Worker,如下图所示。Driver中定义了一个或多个RDD,并调用RDD上的actionWorker则执行RDD分区计算任务。

    2.2 RDD创建

    Spark中创建RDD的创建方式大概可以分为三种:从集合中创建RDD;从外部存储创建RDD;从其他RDD创建。

    由一个已经存在的Scala集合创建,集合并行化。

    val rdd1 = sc.parallelize(Array(1,2,3,4,5,6,7,8))

    而从集合中创建RDDSpark主要提供了两种函数:parallelizemakeRDD。我们可以先看看这两个函数的声明:

    def parallelize[T: ClassTag](
          seq: Seq[T],
          numSlices: Int = defaultParallelism): RDD[T]
     
    def makeRDD[T: ClassTag](
          seq: Seq[T],
          numSlices: Int = defaultParallelism): RDD[T]
     
    def makeRDD[T: ClassTag](seq: Seq[(T, Seq[String])]): RDD[T]

     我们可以从上面看出makeRDD有两种实现,而且第一个makeRDD函数接收的参数和parallelize完全一致。其实第一种makeRDD函数实现是依赖了parallelize函数的实现,来看看Spark中是怎么实现这个makeRDD函数的:

    def makeRDD[T: ClassTag](
        seq: Seq[T],
        numSlices: Int = defaultParallelism): RDD[T] = withScope {
      parallelize(seq, numSlices)
    }

    我们可以看出,这个makeRDD函数完全和parallelize函数一致。但是我们得看看第二种makeRDD函数函数实现了,它接收的参数类型是Seq[(T, Seq[String])]Spark文档的说明是:

       Distribute a local Scala collection to form an RDD, with one or more location preferences (hostnames of Spark nodes) for each object. Create a new partition for each collection item.

       原来,这个函数还为数据提供了位置信息,来看看我们怎么使用:

     

    scala> val guigu1= sc.parallelize(List(1,2,3))
    guigu1: org.apache.spark.rdd.RDD[Int] = ParallelCollectionRDD[10] at parallelize at <console>:21
     
    scala> val guigu2 = sc.makeRDD(List(1,2,3))
    guigu2: org.apache.spark.rdd.RDD[Int] = ParallelCollectionRDD[11] at makeRDD at <console>:21
     
    scala> val seq = List((1, List("slave01")),| (2, List("slave02")))
    seq: List[(Int, List[String])] = List((1,List(slave01)),
     (2,List(slave02)))
     
    scala> val guigu3 = sc.makeRDD(seq)
    guigu3: org.apache.spark.rdd.RDD[Int] = ParallelCollectionRDD[12] at makeRDD at <console>:23
     
    scala> guigu3.preferredLocations(guigu3.partitions(1))
    res26: Seq[String] = List(slave02)
     
    scala> guigu3.preferredLocations(guigu3.partitions(0))
    res27: Seq[String] = List(slave01)
     
    scala> guigu1.preferredLocations(guigu1.partitions(0))
    res28: Seq[String] = List()

    我们可以看到,makeRDD函数有两种实现,第一种实现其实完全和parallelize一致;而第二种实现可以为数据提供位置信息,而除此之外的实现和parallelize函数也是一致的,如下: 

    def parallelize[T: ClassTag](
        seq: Seq[T],
        numSlices: Int = defaultParallelism): RDD[T] = withScope {
      assertNotStopped()
      new ParallelCollectionRDD[T](this, seq, numSlices, Map[Int, Seq[String]]())
    }
     
    def makeRDD[T: ClassTag](seq: Seq[(T, Seq[String])]): RDD[T] = withScope {
      assertNotStopped()
      val indexToPrefs = seq.zipWithIndex.map(t => (t._2, t._1._2)).toMap
      new ParallelCollectionRDD[T](this, seq.map(_._1), seq.size, indexToPrefs)
    }

    都是返回ParallelCollectionRDD,而且这个makeRDD的实现不可以自己指定分区的数量,而是固定为seq参数的size大小。

    由外部存储系统的数据集创建,包括本地的文件系统,还有所有Hadoop支持的数据集,比如HDFSCassandraHBase

    scala> val atguigu = sc.textFile("hdfs://hadoop102:9000/RELEASE")
    atguigu: org.apache.spark.rdd.RDD[String] = hdfs:// hadoop102:9000/RELEASE MapPartitionsRDD[4] at textFile at <console>:24
    

      

  • 相关阅读:
    ACdream 1224 Robbers (贪心)
    HDU 4320 Arcane Numbers 1 (质因子分解)
    在脚本中重定向输入
    呈现数据
    shell中的for、while、until(二)
    shell中的for、while、until
    C 指针疑虑
    结构化命令
    fdisk -c 0 350 1000 300命令
    PC机上的COM1口和COM2口
  • 原文地址:https://www.cnblogs.com/Diyo/p/11300784.html
Copyright © 2020-2023  润新知