1、什么是RDD?
(1) RDD的全称为Resilient Distributed Dataset是一个弹性、可复原的分布式数据集,是Spark中最基本的抽象,是一个不可变的、有多个分区的、可以并行计算的集合。
(2)RDD中并不装真正要计算的数据,而装的是描述信息,描述以后从哪里读取数据,调用了用什么方法,传入了什么函数,以及依赖关系等。
2、使用textFile 方法创建RDD时,分区数计算
2.1、如果用户未设置最小分区数,即取当前CPU核数与2的最小值,验证如下:
通过SparkContext类中的defaultMinPartitions方法查看,由defaultParallelism,可追溯到CoarseGrainedSchedulerBackend类中的 defaultParallelism方法,由此可验证!
2.2、如果用户设置最小分区数,则最小分区数按照用户的输入设定,最小分区数确定后,开启计算创建RDD时的分区数!
2.3、分区数的计算
切片的核心工作在FileInputFomat的getSplits方法中完成, 由computeSplitSize方法计算出分区切片splitSize 的大小://blockSize hadoop中blockSize块的默认大小为128M(早期版本为64M) protected long computeSplitSize(long goalSize, long minSize, long blockSize) { return Math.max(minSize, Math.min(goalSize, blockSize)); } long splitSize = computeSplitSize(goalSize, minSize, blockSize); ``` 2.3.1 goalSize 的计算 ```java long totalSize = 0; // compute total size for (FileStatus file: files) { // check we have valid files if (file.isDirectory()) { throw new IOException("Not a file: "+ file.getPath()); } totalSize += file.getLen(); } long goalSize = totalSize / (numSplits == 0 ? 1 : long totalSize = 0; // compute total size for (FileStatus file: files) { // check we have valid files if (file.isDirectory()) { throw new IOException("Not a file: "+ file.getPath()); } totalSize += file.getLen(); } //numSplits 即刚才确定的最小分区数 long goalSize = totalSize / (numSplits == 0 ? 1 : numSplits);); ``` 2.3.2 minSize的计算 ```java long minSize = Math.max(job.getLong(org.apache.hadoop.mapreduce.lib.input. FileInputFormat.SPLIT_MINSIZE, 1), minSplitSize); //点击minSplitSize,默认取值为1 private long minSplitSize = 1; //最终得到minSize为1 ``` 2.3.3 得到goalSize minSize blockSize 的大小,根据computeSplitSize方法,即可计算出splitSize 的大小。 2.3.4 根据splitSize对文件进行逻辑切分,如果未切分部分的文件 不小于split的1.1倍,则将其切分,如果小于,则停止切分,最后得到文件的逻辑切分数,即RDD的分区数。 ```java while (((double) bytesRemaining)/splitSize > SPLIT_SLOP) { // SPLIT_SLOP 为1.1 String[][] splitHosts = getSplitHostsAndCachedHosts(blkLocations, length-bytesRemaining, splitSize, clusterMap); splits.add(makeSplit(path, length-bytesRemaining, splitSize, splitHosts[0], splitHosts[1])); bytesRemaining -= splitSize; } if (bytesRemaining != 0) { String[][] splitHosts = getSplitHostsAndCachedHosts(blkLocations, length - bytesRemaining, bytesRemaining, clusterMap); - splits.add(makeSplit(path, length - bytesRemaining, bytesRemaining, splitHosts[0], splitHosts[1])); }
3、使用parallelize方法创建RDD时,分区数计算
1、用户可以手动指定输入切片numSlices的数量 ,numSlices的数量与分区数是一
一对应的关系,通过改值可直接确定RDD的分区数;
2、如果用户未指定默认使用该集群CPU的核数 (目前绝大多数CPU核数 大于2核)
//math.max(totalCoreCount.get(), 2) CPU的核数与2取最大值
override def defaultParallelism(): Int = {
conf.getInt("spark.default.parallelism", math.max(totalCoreCount.get(), 2))
}