下面來看看groupByKey和reduceByKey的區別:
val conf = new SparkConf().setAppName("GroupAndReduce").setMaster("local") val sc = new SparkContext(conf) val words = Array("one", "two", "two", "three", "three", "three") val wordsRDD = sc.parallelize(words).map(word => (word, 1)) val wordsCountWithReduce = wordsRDD. reduceByKey(_ + _). collect(). foreach(println) val wordsCountWithGroup = wordsRDD. groupByKey(). map(w => (w._1, w._2.sum)). collect(). foreach(println)
雖然兩個函數都能得出正確的結果, 但reduceByKey函數更適合使用在大數據集上。 這是因為Spark知道它可以在每個分區移動數據之前將輸出數據與一個共用的key
結合。
借助下圖可以理解在reduceByKey里發生了什么。 在數據對被搬移前,同一機器上同樣的key
是怎樣被組合的( reduceByKey中的 lamdba 函數)。然后 lamdba 函數在每個分區上被再次調用來將所有值 reduce成最終結果。整個過程如下:

image
另一方面,當調用 groupByKey時,所有的鍵值對(key-value pair) 都會被移動,在網絡上傳輸這些數據非常沒必要,因此避免使用 GroupByKey。
為了確定將數據對移到哪個主機,Spark會對數據對的key
調用一個分區算法。 當移動的數據量大於單台執行機器內存總量時Spark
會把數據保存到磁盤上。 不過在保存時每次會處理一個key
的數據,所以當單個 key 的鍵值對超過內存容量會存在內存溢出的異常。 這將會在之后發行的 Spark 版本中更加優雅地處理,這樣的工作還可以繼續完善。 盡管如此,仍應避免將數據保存到磁盤上,這會嚴重影響性能。

image
你可以想象一個非常大的數據集,在使用 reduceByKey 和 groupByKey 時他們的差別會被放大更多倍。
摘自:http://www.jianshu.com/p/0c6705724cff