RDD默认分区数
1.概述
说明:当前spark源码分析基于spark版本2.11、spark-on-yarn-cluster模式进行;
2.默认分区数分析
在SparkContext中定义有defaultMinPartitions函数、defaultParallelism函数,在这2个函数中定义了默认分区数的逻辑;
2.1.defaultParallelism函数
在SparkContext实例化过程中,会初始化_taskScheduler属性,将TaskScheduler的实现类TaskSchedulerImpl进行实例化后,赋值给_taskScheduler;
因此,taskScheduler.defaultParallelism
实际调用的是taskSchedulerImpl#defaultParallelism()函数;
class SparkContext(config: SparkConf) extends Logging {
private var _taskScheduler: TaskScheduler = _
private[spark] def taskScheduler: TaskScheduler = _taskScheduler
def defaultParallelism: Int = {
assertNotStopped()
//从taskSchedulerImpl#defaultParallelism函数取值
taskScheduler.defaultParallelism
}
}
2.1.1.taskSchedulerImpl#defaultParallelism函数
在SparkContext实例化过程中,会初始化_schedulerBackend属性,将SchedulerBackend的实现类CoarseGrainedSchedulerBackend进行实例化后,赋值给_schedulerBackend;
并且在实例化TaskSchedulerImpl时会将SchedulerBackend实现类的实例化对象传给TaskSchedulerImpl对象,完成TaskSchedulerImpl对象中backend属性初始化;
因此,backend.defaultParallelism()
调用的是SchedulerBackend实现类的defaultParallelism()函数;
private[spark] class TaskSchedulerImpl(
val sc: SparkContext,
val maxTaskFailures: Int,
isLocal: Boolean = false)
extends TaskScheduler with Logging {
var backend: SchedulerBackend = null
//调用SchedulerBackend实现类的defaultParallelism()函数
override def defaultParallelism(): Int = backend.defaultParallelism()
}
2.1.1.1.CoarseGrainedSchedulerBackend#defaultParallelism函数
org.apache.spark.scheduler.cluster.CoarseGrainedSchedulerBackend是SchedulerBackend实现类之一,其重写了defaultParallelism函数逻辑;
private[spark]
class CoarseGrainedSchedulerBackend(scheduler: TaskSchedulerImpl, val rpcEnv: RpcEnv)
extends ExecutorAllocationClient with SchedulerBackend with Logging {
//全局配置的spark.default.parallelism参数有值就取参数值
//没有值就根据cpu总核数 vs 2 取大值确定
override def defaultParallelism(): Int = {
conf.getInt("spark.default.parallelism", math.max(totalCoreCount.get(), 2))
}
}
2.1.1.2.LocalSchedulerBackend#defaultParallelism函数
org.apache.spark.scheduler.local.LocalSchedulerBackend是SchedulerBackend实现类之一,其同样重写了defaultParallelism函数逻辑;
private[spark] class LocalSchedulerBackend(
conf: SparkConf,
scheduler: TaskSchedulerImpl,
val totalCores: Int)
extends SchedulerBackend with ExecutorBackend with Logging {
//全局配置的spark.default.parallelism参数有值就取参数值
//没有值就根据cpu总核数 取值确定
//org.apache.spark.scheduler.local.LocalSchedulerBackend
override def defaultParallelism(): Int =
scheduler.conf.getInt("spark.default.parallelism", totalCores)
}
2.2.defaultMinPartitions函数
在defaultParallelism函数值(默认分区参数)和2之间取最小值;
class SparkContext(config: SparkConf) extends Logging {
def defaultMinPartitions: Int = math.min(defaultParallelism, 2)
}
3.默认分区数的使用
在使用某些算子时,如果该算子支持通过参数设置分区数,但是不传该参数也可以正常使用该算子,这种情况下,该算子定义时,大多都将默认分区数作为分区参数的默认值了;
常见的如:
创建RDD的算子parallelize()、textFile()、wholeTextFiles()、hadoopRDD();
4.总结
defaultParallelism函数逻辑:
- 全局配置的spark.default.parallelism参数有值,就取参数值
- 全局配置的spark.default.parallelism参数没有设置:CoarseGrainedSchedulerBackend中,在cpu总核数 vs 2之间取最大值
LocalSchedulerBackend中,取cpu总核数;
defaultMinPartitions函数逻辑:
-
spark.default.parallelism参数有值为p:
当p>2时,defaultMinPartitions=2
当p<=2时,defaultMinPartitions=p -
spark.default.parallelism参数无值:
CoarseGrainedSchedulerBackend中,defaultMinPartitions=2
LocalSchedulerBackend中,defaultMinPartitions=min(cpu总核数,2)