spark算子之reparation和coalesce

reparation和coalesce都是spark的基础算子

def repartition(numPartitions: Int)(implicit ord: Ordering[T] = null): RDD[T] = withScope {
    coalesce(numPartitions, shuffle = true)
  }

def coalesce(numPartitions: Int, shuffle: Boolean = false,
               partitionCoalescer: Option[PartitionCoalescer] = Option.empty)
              (implicit ord: Ordering[T] = null)
      : RDD[T] = withScope {
    require(numPartitions > 0, s"Number of partitions ($numPartitions) must be positive.")
    if (shuffle) {
      /** Distributes elements evenly across output partitions, starting from a random partition. */
      val distributePartition = (index: Int, items: Iterator[T]) => {
        var position = new Random(hashing.byteswap32(index)).nextInt(numPartitions)
        ......
  }

通过源码可以看到reparation也是调用了coalesce的shuffle为true的方法,而coalesce方法默认shuffle是false。
大家都知道他们的区别是reparation发生了shuffle,coalesce没有发生shuffle。shuffle就是打散数据的意思。reparation会将数据按照指定的分区个数,将数据按照指定的分区规则将数据从新分布,然后reduce端直接拉取处理对应分区索引的数据。coalesce只是将多个分区的数据合并到一个分区去处理,并不会发生数据的从新分布。

val sparkSession = createSparkSession("demo")
    sparkSession.sparkContext.setLogLevel("WARN")
    val srcRDD: RDD[Int] = sparkSession.sparkContext.parallelize(Seq(1, 2, 3, 4, 5, 6, 7, 8, 9), 3)
    val resRDD = srcRDD.mapPartitionsWithIndex((index,itr) => fun(index,itr)).collect()
    println(resRDD.mkString("|"))
    val repartionRDD = srcRDD.repartition(2).mapPartitionsWithIndex((index,itr) => fun(index,itr)).collect()
    println(repartionRDD.mkString("|"))
    val coalesceRDD = srcRDD.coalesce(2).mapPartitionsWithIndex((index,itr) => fun(index,itr)).collect()
    println(coalesceRDD.mkString("|"))
    sparkSession.stop()

  }

  def fun(index:Int,itr:Iterator[Int]) = {
    val arrayBuffer = new ArrayBuffer[String]()
    while (itr.hasNext) {
      arrayBuffer += s"index:${index},value:${itr.next()}"
    }
    arrayBuffer.iterator
  }
# 输出结果
index:0,value:1|index:0,value:2|index:0,value:3|index:1,value:4|index:1,value:5|index:1,value:6|index:2,value:7|index:2,value:8|index:2,value:9
index:0,value:1|index:0,value:3|index:0,value:5|index:0,value:7|index:0,value:9|index:1,value:2|index:1,value:4|index:1,value:6|index:1,value:8
index:0,value:1|index:0,value:2|index:0,value:3|index:1,value:4|index:1,value:5|index:1,value:6|index:1,value:7|index:1,value:8|index:1,value:9

可以看到reparation是会将数据从新分布的,coalesce直接将原始分区1和2的数据直接合并到一个分区去处理,可以想象到数据的从新打散是要比直接合并分区的数据耗费更多时间的,这也是为什么shuffle就会耗时更久的秘密。

延伸:可以看到reparation的分区规则默认是HashPartitioner,但是并不是按照key直接hash的,而是使用一个随机数的hash作为了key

欢迎对技术感兴趣的小伙伴一起交流学习^^

你可能感兴趣的:(spark算子之reparation和coalesce)