Spark源码-spark算子-1-构建RDD的算子

26 篇文章 0 订阅
25 篇文章 2 订阅

1.概述

说明:当前spark源码分析基于spark版本2.11进行;

下面这段话引自弹性分布式数据集 (RDDs)

Spark 围绕弹性分布式数据集(RDD) 的概念展开,RDD 是可以并行操作的元素的容错集合。创建 RDD 有两种方法:并行化 驱动程序中的现有集合,或引用外部存储系统中的数据集,例如共享文件系统、HDFS、HBase 或任何提供 Hadoop InputFormat 的数据源。

接下来将基于源码进一步了解RDD的创建;

2.RDD创建方式

2.1.根据驱动程序中现有并行化集合创建RDD

2.1.1.parallelize方式创建RDD

通过SparkContext#parallelize()可以实现根据现有并行化集合创建RDD的需要;

在调用parallelize过程时,可以指定RDD的分区数,如果指定,将根据默认分区数进行设置;

通过parallelize方式创建的RDD实现类为ParallelCollectionRDD;

class SparkContext(config: SparkConf) extends Logging {
  /**
  * seq:用于创建RDD的并行化集合
  * numSlices:分区数
  */
  def parallelize[T: ClassTag](
      seq: Seq[T],
      numSlices: Int = defaultParallelism): RDD[T] = withScope {
    assertNotStopped()
    new ParallelCollectionRDD[T](this, seq, numSlices, Map[Int, Seq[String]]())
  }
}

例:

val data = Array(1, 2, 3, 4, 5)
val distData = sc.parallelize(data)
val distData1 = sc.parallelize(data,3)

2.2.根据外部存储系统中的数据集创建RDD

2.2.1.textFile-根据本地文本文件创建RDD

通过textFile创建的RDD实现类为MapPartitionsRDD;

先使用hadoopFile函数构建HadoopRDD,然后使用map函数构建MapPartitionsRDD并返回;

文件读取方式:TextInputFormat、key的格式:LongWritable、value的格式:Text;

textFile()算子可以一次处理一批文件,path参数通过逗号分割不懂的文件路径;

class SparkContext(config: SparkConf) extends Logging {
  
  def textFile(
      path: String,
      minPartitions: Int = defaultMinPartitions): RDD[String] = withScope {
    assertNotStopped()
    //文件读取方式:TextInputFormat;key的格式:LongWritable;value的格式:Text
    hadoopFile(path, classOf[TextInputFormat], classOf[LongWritable], classOf[Text],
      minPartitions).map(pair => pair._2.toString).setName(path)
  }
}

例:

val distFile = sc.textFile("data.txt")
2.2.1.1.hadoopFile-根据文件创建hadoopRDD
class SparkContext(config: SparkConf) extends Logging {
  
  def hadoopFile[K, V](
      path: String,
      inputFormatClass: Class[_ <: InputFormat[K, V]],
      keyClass: Class[K],
      valueClass: Class[V],
      minPartitions: Int = defaultMinPartitions): RDD[(K, V)] = withScope {
    assertNotStopped()

    // 强制加载hdfs-site.xml.
    FileSystem.getLocal(hadoopConfiguration)

    // 广播序列化后的hadoop配置文件对象
    val confBroadcast = broadcast(new SerializableConfiguration(hadoopConfiguration))
    //设置文件读取路径:路径参数支持以逗号分割的一批路径,即可以同时读取一批文件
    val setInputPathsFunc = (jobConf: JobConf) => FileInputFormat.setInputPaths(jobConf, path)
    new HadoopRDD(
      this,
      confBroadcast,
      Some(setInputPathsFunc),
      inputFormatClass,
      keyClass,
      valueClass,
      minPartitions).setName(path)
  }
}

2.2.2.wholeTextFiles-根据文件目录创建RDD

通过wholeTextFiles创建的RDD实现类为WholeTextFileRDD;

先构建WholeTextFileRDD,然后使用map函数转为MapPartitionsRDD;

文件读取方式:WholeTextFileInputFormat、key格式:Text、value格式:Text;

class SparkContext(config: SparkConf) extends Logging {
  def wholeTextFiles(
      path: String,
      minPartitions: Int = defaultMinPartitions): RDD[(String, String)] = withScope {
    assertNotStopped()
    val job = NewHadoopJob.getInstance(hadoopConfiguration)
    
    NewFileInputFormat.setInputPaths(job, path)
    val updateConf = job.getConfiguration
    //文件读取方式:WholeTextFileInputFormat、key格式:Text、value格式:Text;
    new WholeTextFileRDD(
      this,
      classOf[WholeTextFileInputFormat],
      classOf[Text],
      classOf[Text],
      updateConf,
      minPartitions).map(record => (record._1.toString, record._2.toString)).setName(path)
  }
}

2.2.3.sequenceFile-根据hadoop序列化文件创建RDD

通过sequenceFile创建的RDD实现类为HadoopRDD;

直接使用hadoopFile构建HadoopRDD实例化对象;

class SparkContext(config: SparkConf) extends Logging {
  def sequenceFile[K, V](path: String,
      keyClass: Class[K],
      valueClass: Class[V],
      minPartitions: Int
      ): RDD[(K, V)] = withScope {
    assertNotStopped()
    val inputFormatClass = classOf[SequenceFileInputFormat[K, V]]
    //直接使用hadoopFile构建HadoopRDD实例化对象
    hadoopFile(path, inputFormatClass, keyClass, valueClass, minPartitions)
  }
}

2.2.4.hadoopRDD-根据Hadoop JobConf创建RDD

构建HadoopRDD实例化对象;

class SparkContext(config: SparkConf) extends Logging {
  
  def hadoopRDD[K, V](
      conf: JobConf,
      inputFormatClass: Class[_ <: InputFormat[K, V]],
      keyClass: Class[K],
      valueClass: Class[V],
      minPartitions: Int = defaultMinPartitions): RDD[(K, V)] = withScope {
    assertNotStopped()

    // 强制加载hdfs-site.xml.
    FileSystem.getLocal(conf)

    // 在广播JobConf之前,向它添加必要的安全凭据。
    SparkHadoopUtil.get.addCredentials(conf)
    new HadoopRDD(this, conf, inputFormatClass, keyClass, valueClass, minPartitions)
  }
}

3.默认分区数

spark.default.parallelism参数有值为p:
当p>2时,defaultMinPartitions=2,默认最小分区数为2;
当p<=2时,defaultMinPartitions=p,默认最小分区数为p;
spark.default.parallelism参数无值:
集群模式下,defaultMinPartitions=2,默认最小分区数为2;
local模式下,defaultMinPartitions=min(cpu总核数,2);

默认分区数详情参考【默认分区数】;

4.创建RDD总结

1、可以根据并行化集合、外部文件系统数据集2中方式创建RDD;

2、外部文件系统包括本地文件系统、HDFS、Cassandra、HBase、Amazon S3等。Spark 支持文本文件、SequenceFiles和任何其他 Hadoop InputFormat。

3、构建方法vs构建的实例化对象:

parallelize --> ParallelCollectionRDD;

wholeTextFiles、textFile --> MapPartitionsRDD;

sequenceFile、hadoopRDD -->HadoopRDD;

4、创建的RDD的分区数:有参数根据参数,无参数使用默认分区数;

5、通过分析发现,不论那种构建RDD的方式,其算子都是定义在SparkContext中;

5.参考资料

弹性分布式数据集 (RDDs)

默认分区数

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值