说明:当前spark源码分析基于spark版本2.11进行;
下面这段话引自弹性分布式数据集 (RDDs):
Spark 围绕弹性分布式数据集(RDD) 的概念展开,RDD 是可以并行操作的元素的容错集合。创建 RDD 有两种方法:并行化 驱动程序中的现有集合,或引用外部存储系统中的数据集,例如共享文件系统、HDFS、HBase 或任何提供 Hadoop InputFormat 的数据源。
接下来将基于源码进一步了解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)
通过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")
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)
}
}
通过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)
}
}
通过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)
}
}
构建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)
}
}
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);
默认分区数详情参考【默认分区数】;
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中;
弹性分布式数据集 (RDDs)
默认分区数