JerryLead / ApacheSparkBook

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

page59,关于groupByKey在不同partitoner时的shuffle问题

zdkzdk opened this issue · comments

1.你说groupByKey在左右2个算子的partitioner相同时不会进行shuffle,这里的partitioner相同应该怎么理解。应该是分区器的类型和分区都要相同吗。如果左边的分区数比右边大,子RDD的一个分区依赖父RDD多个分区的全部,应该也不需要shuffle吧。
2.groupByKey的默认分区器就是hashPartitoner吗,可以换吗

  1. 对于rdd2 = rdd1.groupByKey(partitioner1),当partitioner1 == rdd1采用的partitioner,也就是你说的分区器的类型和分区都要相同时,groupByKey()不进行shuffle,而只进行mapPartitions()操作,详见combineByKeyWithClassTag代码。除此以外,groupByKey()将进行shuffle。

    “如果左边的分区数比右边大,子RDD的一个分区依赖父RDD多个分区的全部“,这种情况属于NarrowDependency(见图3.2)不进行shuffle,不过这种情况目前只会出现在用户自定义的算子中,Spark代码中的groupByKey()算子没有对这种情况进行特殊检查和处理,因为进行检查的代价太高(检查保证相同key的records会被放到同一个partition中),所以目前groupByKey()的逻辑就是partitioner相同不进行shuffle,除此以外都进行shuffle。

  2. 可以换,比如下面代码将HashPartitioner换为RangePartitioner,不管什么partitioner,只要能将相同key的records放在同一分区即可。

package basic.transfromation

import org.apache.spark.sql.SparkSession
import org.apache.spark.{HashPartitioner, RangePartitioner}

object GroupByKeyExample {
  def main(args: Array[String]): Unit = {
    val spark = SparkSession
      .builder
      .appName("group by key example")
      .master("local[1]")
      .getOrCreate()
    val sc = spark.sparkContext

    val inputRDD = sc.parallelize(Array[(Int,Char)](
      (2,'b'),(3,'c'),(1,'a'),(4,'d'),(5,'e'),(3,'f'),(2,'b'),(1,'h'),(2,'i')
    ),3)

    val inputRDD2 = inputRDD.partitionBy(new HashPartitioner(3))

    println("------------input rdd----------")
    inputRDD2.mapPartitionsWithIndex((pid, iter)=>{
      iter.map( value => "PID: " + pid + ", value: " + value)
    }).foreach(println)

    //val resultRDD = inputRDD2.groupByKey(3)
    val resultRDD = inputRDD2.groupByKey(new RangePartitioner(3, inputRDD2))
    println(resultRDD.toDebugString)
    println("------------result rdd----------")
    resultRDD.mapPartitionsWithIndex((pid, iter)=>{
      iter.map( value => "PID: " + pid + ", value: " + value)
    }).foreach(println)

    System.in.read()
  }
}