RDD分区
- 创建RDD时自定义分区数量
- 根据计算机Core个数确定默认分区数量
核心代码
override def defaultParallelism(): Int =
scheduler.conf.getInt("spark.default.parallelism", totalCores)
- 首选SparkConf配置的spark.default.parallelism分区数量
- 如果没有配置,则采用计算机的核心数量totalCores作为分区数量
分析源码步骤
- 程序- -分区源码入口- -.makeRDD()
- 默认并行度defaultParallelism
- 默认并行度defaultParallelism
- 默认并行度defaultParallelism
- 此时defaultParallelism位于TaskScheduler.scala中,次未见类型为Trait类型,没有函数体,在Intellij IDEA中,按快捷键ctrl+H查看文件继承层级关系,查看TaskSchedulerImpl.scala文件
- 默认并行度defaultParallelism
- 同上,ctrl+H查看层级关系,查看LocalSchedulerBackend.scala文件
- 默认并行度defaultParallelism,核心代码
- conf为SparkConf环境配置变量
RDD分区数据分配
- 根据数据类型(Range or 其他)采用不同的数据划分策略,本文以List类型数据为例
- 数据分配方式计算,与切片数量,数据长度有关
核心代码
def positions(length:Long,numSlices:Int):Iterator[(Int,Int)]={
//0~切片个数,进行遍历
(0 until numSlices).iterator.map{i=>
val start=((i*length)/numSlices).toInt
val end=(((i+1)*length)/numSlices).toInt
(start,end)
}
}
例:
数据:4, 3, 2,1, 0
切片数量:3
调用position方法
length = 5 //数据长度
numSlice = 3 //分区数量
0 until numSlices => 0, 1, 2 //分区索引
if i=0
start = 0
end = 1
=> 切片1的数据(4)
if i=1
start = 1 * 5 / 3 = 1
end = 2 * 5 / 3 = 3
=>切片2的数据(3, 2)
if i=2
start = 2 * 5 / 3 = 3
end = 3 * 5 / 3 = 5
=>切片3的数据(1,0)
分析源码步骤
- 程序入口- - 数据分配源码 - - makeRDD()
- 调用parallelize函数
- 声明ParallelCollectionRDD类对象
- ParallelCollectionRDD类中重写getPartitions方法,调用slice方法
- 划分数据的核心方法ParallelCollectionRDD(函数分成了两张图片)
- 传入参数:序列seq,切片个数numSlices
- 先判断numSlices >= 1
- 定义划分position方法,划分出起始位置和结束位置start和end
- seq进行模式匹配
- case r 和 nr均为匹配Range(范围)类型的数据
- 其他数据类型转换为数组进行范围划分