前言
本文主要从源码角度分析下cogroup算子的原理。把cogroup单独拿出来介绍是因为它是很多其它算子的基础,如join、leftjoin、rightjoin、fullouterjoin、intersection等。cogroup是一个比较底层的算子,直接应用很少,先介绍一下它的用法和功能
用例
cogroup是PairRDDFunctions类中的一个算子,作用在元素类型为(k,v)的RDD上,而且是至少两个RDD才能进行cogroup运算。下面是一个cogroup算子使用的例子:
import org.apache.spark.{SparkConf, SparkContext}
object Test1 {
def main(args: Array[String]): Unit = {
val sc = new SparkContext(new SparkConf().setMaster("local[*]").setAppName("test"))
val rdd1 = sc.parallelize(List(("a", 10), ("b", 20), ("a", 30), ("c", 40)), 2)
val rdd2 = sc.parallelize(List(("a", 100), ("d", 20)))
val rdd3 = rdd1.cogroup(rdd2)
rdd3.foreach(println)
sc.stop()
}
}
返回结果
(d,(CompactBuffer(),CompactBuffer(20)))
(a,(CompactBuffer(10, 30),CompactBuffer(100)))
(c,(CompactBuffer(40),CompactBuffer()))
(b,(CompactBuffer(20),CompactBuffer()))
其原理简单的说就是:对于同一个key,第一个RDD中的value汇总成一个CompactBuffer(可以简单的理解为一个数组),然后将所有RDD的CompactBuffer汇总成一个元组,最后返回的是(key, 元组)的二元组。
源码
def cogroup[W](other: RDD[(K, W)], partitioner: Partitioner)
: RDD[(K, (Iterable[V], Iterable[W]))] = self.withScope {
if (partitioner.isInstanceOf[HashPartitioner] && keyClass.isArray) {
throw new SparkException("HashPartitioner cannot partition array keys.")
}
// 生成CoGroupedRDD,元素类型为: (k, Array(v1, v2)), v1、v2分别为第一个rdd、第二个rdd元素的集合,类型为Iterable
val cg = new CoGroupedRDD[K](Seq(self, other), partitioner)
// 将cg的返回类型转化为(key, (Iterable, Iterable))
cg.mapValues { case Array(vs, w1s) =>
(vs.asInstanceOf[Iterable[V]], w1s.asInstanceOf[Iterable[W]])
}
}
cogroup的源码比较简单,大家看看我写代码注释,大概就能明白其原理。关于CoGroupedRDD,我目前暂时没有完全弄懂里面的细节,后续弄懂了再补一篇分析其原理的文章