Spark基础随笔:分区详解

来源:互联网 发布:戏子家事天下知 编辑:程序博客网 时间:2024/05/21 20:30

1.分区

分区是RDD内部并行计算的一个计算单元,RDD的数据集在逻辑上被划分为多个分片,每一个分片称为分区,分区的格式决定了并行计算的粒度,而每个分区的数值计算都是在一个任务中进行的,因此任务的个数,也是由RDD(准确来说是作业最后一个RDD)的分区数决定。

2.分区的个数

RDD分区的一个分区原则:尽可能是得分区的个数等于集群核心数目

下面我们仅讨论Spark默认的分区个数,这里分别就parallelizetextFile具体分析其默认的分区数

无论是本地模式、Standalone模式、YARN模式或Mesos模式,我们都可以通过spark.default.parallelism来配置其默认分区个数,若没有设置该值,则根据不同的集群环境确定该值

  • 本地模式:默认为本地机器的CPU数目,若设置了local[N],则默认为N
  • Apache Mesos:默认的分区数为8
  • Standalone或YARN:默认取集群中所有核心数目的总和,或者2,取二者的较大值
结论:
  1. 对于parallelize来说,没有在方法中的指定分区数,则默认为spark.default.parallelism
  2. 对于textFile来说,没有在方法中的指定分区数,则默认为min(defaultParallelism,2),而defaultParallelism对应的就是spark.default.parallelism。如果是从hdfs上面读取文件,其分区数为文件分片数(128MB/片)

3.案例

比如我想把所有的(key,value)里面的key较小的value都累加到key较大的上面去。如(3, 6),(5,4),(6, 2)
结果(6,2+4+6=12),(5,4+6=10),(3,6)
    val data = Array((3, 6),(5,4),(6, 2)) //key升序    val rdd1 = sc.parallelize(data, 2) //设置2分区    var sum = 0    rdd1.foreach(f => {      println((f._1,sum+f._2) + "--" + sum)      sum += f._2    })
但很遗憾,结果并我们所想
(3,6)--0(5,4)--0(6,6)--4
注意到(3,6)和(5,4)都是0,我们猜测它们的执行代码不在同台机器上(确切地说应该是不在同一分区),我们使用glom来验证下,glom函数会把RDD分区数据组装到数组类型的RDD中
scala> rdd1.glom.collectres28: Array[Array[(Int, Int)]] = Array(Array((3,6)), Array((5,4), (6,2)))
Ok,我们的猜想得到了验证,果然它们不在一个分区中。问题暴力简单的解决方法是使用repartition把分区数置1




1 2
原创粉丝点击