概述
RDD是Spark的核心,其创建方式可以通过其他RDD转换而来,或者从存储系统中创建,比如本地文件系统或者hdfs。其中SparkContext中的textFile便可以从文件系统中生产RDD,其实质便是new出了RDD的实例,其中一个重要的信息便是分区。下面将详细介绍。
textFile解析
调用textFile可以用下面的方式:
SparkSession spark = SparkSession
.builder()
.appName("JavaWordCount")
.getOrCreate();
JavaRDD<String> lines = spark.sparkContext().textFile(args[0], 2).toJavaRDD();
或者:
JavaRDD<String> lines = spark.read().textFile(args[0]).javaRDD();
其中调用SparkContext中的textFile,会调用到SparkContext.scala中的hadoopFile方法,最关键的就是new HadoopRDD。
在new HadoopRDD所需参数中有一个minPartitions,这是从textFile函数中第二个参数传进去的,如例子中为2,如果没有,则取默认值。
第二种方式调用textFile,最终会调用到DataSourceScanExec.scala中的createNonBucketedReadRDD方法,最终new FileScanRDD
分区数的计算
RDD的分区数决定了task的数量,需要关注。可以使用RDD的getNumPartitions方法查询该RDD的分区数。
在textFile中可以传入一个最小分区数minPartitions
源码中计算逻辑如下:
long goalSize = totalSize / (long)(numSplits == 0 ? 1 : numSplits); //totalSize为文件总大小,numSplits即textFile中传入的最小分区数minPartitions
long minSize = Math.max(job.getLong("mapreduce.input.fileinputformat.split.minsize", 1L), this.minSplitSize);
long blockSize = file.getBlockSize(); //获取hdfs一个block的大小,默认128M
long splitSize = Math.max(minSize, Math.min(goalSize, blockSize)); //splitSize则为1个分区的大小
long numPartitions = totalSize % splitSize == 0 ? totalSize / splitSize : totalSize / splitSize + 1;
源码跟踪:
org.apache.spark.rdd.HadoopRDD#getPartitions -> org.apache.hadoop.mapred.FileInputFormat#getSplits
如果没有明确指定分区的情况下,hdfs有多少个block,其RDD就会有多少个分区
总结
调用textFile生成RDD的实质是new 出了RDD的实例,重点关注下分区数的计算即可。
参考
https://www.jianshu.com/p/e33...
https://segmentfault.com/a/11...
https://blog.csdn.net/u010990...
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。