-
- RDD的創建和保存
- 1.1 textFile
從HDFS中讀取一個文本文件 - 1.2 makeRDD、parallelize
都會創建一個新的ParallelCollectionRDD對象。如果makeRDD中的數據是Seq[T]結構,就會調用parallelize方法,不過makeRDD還可以將Seq[(T, Seq[String])]結構的數據轉變成RDD。
makeRDD源碼
parallelize源碼
defaultParallelism源碼解釋 - 1.3 saveAsTextFile
將RDD保存為一個壓縮文本文件。
-
- 轉換算子
- 2.1 不會shuffle的
- 2.1.1 map、flatMap、mapPartitions
new一個新的MapPartitionsRDD對象,并調用Scala相應集合類的map或flatMap方法。
map和flatMap相應源碼
mapPartitions類源碼 - 2.1.2 mapValues、flatMapValues
mapValues和flatMapValues是在PairRDDFunctions類中定義的,而map和flatMap是在RDD類中定義的,說明mapValues和flatMapValues使用場景相對更小一點,其處理的RDD形式必須是鍵值對。從源碼來看,mapValues和flatMapValues只對鍵值對中的值進行處理,而且一定保證分區不變。
mapValues和flatMapValues相應源碼 -
2.1.3 coalesce
對RDD進行合并分區。從源碼解釋上來看,coalesce是窄依賴關系,不需要shuffle(參數shuffle默認是false)。但源碼中也提到,如果合并后分區數很小,很可能導致計算在較少的節點上進行,此時可以將shuffle設置為true。
coalesce源碼解釋
coalesce源碼接著看源碼,可見coalesce具體進行過程受到shuffle參數的影響。當shuffle為false時,coalesce會創建新的CoalescedRDD類,CoalescedRDD類要求參數numPartitions大于0。coalesce主要是將父RDD合并成更少的分區,如果numPartitions大于原RDD分區數,那么新RDD分區數還是和原RDD分區數一樣;如果numPartitions小于原RDD分區數,就會對partitions進行分組(group),具體實現可見PartitionCoalescer類及其throwBalls方法。
PartitionCoalescer類的throwBalls方法
- 2.1.1 map、flatMap、mapPartitions
- 2.2 會shuffle的
- 2.2.1 intersection
intersection的實現主要是利用了cogroup方法。
cogroup相應源碼
intersection相應源碼
不過這里還有一點有些疑惑,那就是構建CogroupRDD時是如何確定結果RDD的分區數?源碼中與partition相關的代碼如下,但是我不太理解,。
CoGroupRDD分區邏輯源碼 - 2.2.2 subtract
subtract的實現是利用了SubtractedRDD類,調用subtractByKey方法,得到新的SubtractedRDD對象。subtract并沒有用cogroup算子,而是為之新創造了一個類SubtractedRDD。原因是cogroup會將兩個原RDD的key全部保留在內存中,但是SubtractedRDD中只會保留RDD_A的key,RDD_B的key會流式傳過來。當RDD_A小于RDD_B時該優化可以讓系統使用RDD_A的分區,而不用擔心RDD_B的大小導致內存不足。源碼中解釋如下:
SubtractedRDD源碼解釋和
。
SubtractedRDD計算過程 - 2.2.3 join、leftOuterJoin、fullOuterJoin
join類型算子都是基于cogroup算子計算的。前面已經寫了,cogroup算子會將兩個RDD相同的key和相應value組合在一起,最后的結果形式是(key, (iterable(v1), interable(v2)))。最后用嵌套for循環組合(iterable(v1)和(iterable(v2)就可以得到join結果。不同的join實現的不同點在于兩個iterable組合時對空iterable的處理方式。 -
2.2.4 groupByKey
將RDD中相同key的元素的value全部放到一個sequence中。這個操作是很耗費資源的,因為聚集過程中并沒有value的聚集,僅僅是收集起來放到一個sequence中。源碼中還提到groupByKey會將所有鍵值對都保存在內存中,所以可能會導致OOM。
groupByKey源碼解釋 - 2.2.5 reduceByKey、aggregateByKey
如果是要對RDD中元素按key分組后對values進行聚合,那么就可以將groupByKey換成reduceByKey或aggregateByKey。
reduceByKey算子和aggregateByKey算子都是基于combineByKeyWithClassTag實現的
reduceByKey源碼
aggregateByKey源碼
補充:aggregateByKey還有個優勢在于combOp的輸入參數類型不需要一致,也就是說,使用reduceByKey的話,map聚合后的value得和沒聚合前的value類型一樣,但是aggregateByKey就沒這樣的要求。比如,如果要同時計算用戶的最大收入和最小收入,用aggregateByKey的話就可以直接對<用戶, 收入>進行操作,最后得到<用戶, <最大收入, 最小收入>>,但是用reduceByKey就得先將原數據形式改為<用戶, <收入, 收入>>,得保證和最終想得到的格式<用戶, <最大收入, 最小收入>>一樣。
至于combineByKeyWithClassTag,我個人覺得就是對MapReduce中的combine函數的實現。
- 2.2.1 intersection
-
- 行動算子
-
3.1 collect
collect會調用sc.runJob將數據全部拉取到driver端存在一個Array中。
collect源碼 - 3.2 count、countByKey、countByValue
count調用sc.runJob將數據拉回driver端并求和
countByKey會將原PairRDD的值變成1L,然后利用reduceByKey和collect得到結果Map
countByValue會將原RDD變成(value, null),然后基于countByKey得到結果Map
count源碼
countByKey源碼
countByValue源碼,這里挖個坑。
-
3.3 foreach、foreachPartition
先貼上源碼:
foreach和foreachPartition源碼從源碼中可以看出,二者最大的區別在于對傳入方法f使用。前者是方法f作用于單個RDD元素,后者是方法f作用于整個RDD分區
- 3.4 first、take、top
take(num)是取回RDD的前num個元素,工作方式是先掃描一個工作分區,然后根據該分區返回結果評估是否還需要掃描其他分區以滿足num數量。注意,如果RDD是"Nothing"或"Null",則會返回異常。
take源碼
first源碼
takeOrdered源碼 -
3.5 sortBy
調用sortByKey方法,創建一個新的排好序的ShuffledRDD。這里根據名字猜測一下,既然新的RDD是ShuffledRDD,說明該RDD的創建應該是進行了shuffle,所以最后的結果應該是全局排序的。
sortByKey源碼
常用Spark算子總結
最后編輯于 :
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。
推薦閱讀更多精彩內容
- spark性能優化:數據傾斜調優 - LW_ICE - 博客頻道 - CSDN.NEThttp://blog.cs...