shuffle算子
1、groupByKey
(针对于对偶元组类型的数据进行按key分组操作)
(1)经groupByKey处理后的数据得到的结果泛型可以是:(String,Iterator(Int));
(2)调用groupByKey后生成一个shuffledRDD;
(3)key相同的进入同一节点的同一分区中;
(4)如何保证key相同的进入同一台机器的同一分区中?一个分区中只有一个key吗?
①溢写磁盘,标识key,拉取属于自己的key到同一分区;下游到上游拉取属于自己的key到同一分区的同一组内;
②一个分区中可能有0个,可能有1个,可能有多个key,取决于分区器(默认使用hashPartitioner分区器)。
(5)shuffle之前一定要获取输入切片,知道下游的分区数量;
(6)hashPartitioner的底层实现:
class HashPartitioner(partitions: Int) extends Partitioner {
require(partitions >= 0, s"Number of partitions ($partitions) cannot be negative.")
def numPartitions: Int = partitions
def getPartition(key: Any): Int = key match {
case null => 0
case _ => Utils.nonNegativeMod(key.hashCode, numPartitions)
}
override def equals(other: Any): Boolean = other match {
case h: HashPartitioner =>
h.numPartitions == numPartitions
case _ =>
false
}
override def hashCode: Int = numPartitions
}
private[spark] object Utils extends Logging {
def nonNegativeMod(x: Int, mod: Int): Int = {
val rawMod = x % mod
rawMod + (if (rawMod < 0) mod else 0)
}
}
①在executor中调用getPartition方法,得到key的分区号(shufflewrite之前,shufflewrite:为shuffle做准备,溢写到磁盘中)
②case null:进入0号分区;
③如果key为null,会出现什么情况:
程序执行时如果批量放入内存中计算ÿ