Spark:RDD分区数和分区器

两个概念:

  • 分区partition
  • 分区器partitioner

partition

RDD有个partitions方法:
final def partitions: Array[Partition]

能够返回一个数组,数组元素是RDD的partition。

partition是RDD的最小数据处理单元,可以看作是一个数据块,每个partition有个编号index。

一个partition被一个map task处理。

partitioner

MR任务的map阶段的处理结果会进行分片(也可以叫分区,这个分区不同于上面的分区),分片的数量就是reduce task的数量。

具体怎么分片由分区器partitioner决定,spark中默认定义了两种partitioner:

  • 哈希分区器(Hash Partitioner)
  • 范围分区器(Range Partitioner)

hash分区器会根据key-value的键值key的hashcode进行分区,速度快,但是可能产生数据偏移,造成每个分区中数据量不均衡。

range分区器会对现有rdd中的key-value数据进行抽样,尽量找出均衡分割点,一定程度上解决了数据偏移问题,力求分区后的每个分区内数据量均衡,但是速度相对慢。

partitioner分区详情

在对父RDD执行完Map阶段任务后和在执行Reduce阶段任务前,会对Map阶段中间结果进行分区。
分区由父RDD的partitioner确定,主要包括两部分工作:

  1. 确定分区数量(也就是reduce task数量),也是子RDD的partition数量。
  2. 决定将Map阶段中间结果的每个key-value对分到哪个分区上。

假设一个父RDD要执行reduceByKey任务,我们可以显式的指定分区器:

val rdd_child = rdd_parent.reduceByKey(new HashPartitioner(3), _+_)

HashPartitioner构造参数3就是分区数量,也是启动的reduce task数量,也是reduceByKey结果返回的子RDD的partitions方法返回的数组的长度。

如果没有显式指定分区器,则会调用org.apache.spark包下伴生对象PartitionerdefaultPartitioner静态方法返回的分区器作为默认分区器。

defaultPartitioner返回默认分区器的过程如下:
尝试利用父RDD的partitioner,如果父RDD没有partitioner,则会查看sparkConf中是否定义了 spark.default.parallelism 配置参数,如果定义了就返回new HashPartitioner(sc.defaultParallelism)作为默认分区器,如果没定义就返回new HashPartitioner(rdd_parent.partitions.length)作为默认分区器——
以下是源码:

//org.apache.spark包下伴生对象object Partitioner的方法
def defaultPartitioner(rdd: RDD[_], others: RDD[_]*): Partitioner = {
  val rdds = (Seq(rdd) ++ others)
  val hasPartitioner = rdds.filter(_.partitioner.exists(_.numPartitions > 0))
  if (hasPartitioner.nonEmpty) {
    hasPartitioner.maxBy(_.partitions.length).partitioner.get
  } else {
    if (rdd.context.conf.contains("spark.default.parallelism")) {
      new HashPartitioner(rdd.context.defaultParallelism)
    } else {
      new HashPartitioner(rdds.map(_.partitions.length).max)
    }
  }
}

更具体的,无论是以本地模式、Standalone 模式、Yarn 模式或者是 Mesos 模式来运行 Apache Spark,分区的默认个数等于对spark.default.parallelism的指定值,若该值未设置,则 Apache Spark 会根据不同集群模式的特征,来确定这个值。

posted @ 2019-01-04 17:24  xuejianbest  阅读(3981)  评论(0编辑  收藏  举报