RDD是Spark對各種數據計算模型的統一抽象,被用於迭代計算過程以及任務輸出結果的緩存讀寫。算法
在全部MapReduce框架中,shuffle是鏈接map任務和reduce任務的橋樑。shuffle性能優劣直接決定了緩存
整個計算引擎的性能和吞吐量。性能優化
MappedRDD的iterator方法網絡
shuffle是全部MapReduce計算框架所必須通過的階段,shuffle用於打通map任務的輸出與reduce任務的輸入,app
map任務的中間輸出結果按照key值哈希後分配給某一個reduce任務。框架
目前Spark的shuffle已經作了多種性能優化,主要解決方案包括:函數
1>將map任務輸出的bucket(給每一個partition的reduce)合併到同一個文件中,這解決了bucket數量很對多,可是自己數據體積不大性能
時,形成shuffle很頻繁,磁盤I/O成爲性能瓶頸的問題。fetch
2>map任務逐條輸出計算結果,而不是一次性輸出到內存中,並使用緩存及其聚合算法對中間結果進行聚合,大大減少了中間結果所佔的內存大小。大數據
3>緩存溢出判斷,超過大小時,將數據寫入磁盤,防止內存溢出
4>reduce任務對拉取到的map任務中間結果逐條讀取,而不是一次性讀入內存,並在內存中使用聚合和排序,大大減小了數據佔用內存
5>reduce任務將要拉取的Block按照BlockManager地址劃分,而後將同一BlockManager地址中的Block累計爲少許網絡請求,減小網絡I/O
首先理解兩個概念:
bypassMergeThreshold:傳遞到reduce端再作merge操做的閾值。默認200
bypassMergeSort:標記是否傳遞到reduce端再作合併和排序
map端計算結果緩存有三種處理方式:
1.map端對計算結果在緩存中執行聚合和排序。
2.map不適用緩存,也不執行聚合和排序,直接調用spillToPartitionFiles將各個partition直接寫到本身存儲文件,
最後由reduce端對計算結果執行合併和排序。
3.map端對計算結果簡單緩存。
在一個任務的分區數量一般不少,若是隻是簡單地將數據存儲到Executor上。在執行reduce任務時會存在大量的網絡I/O操做。
這時網絡I/O將成爲系統性能的瓶頸,reduce任務讀取map任務的計算結果變慢,致使其餘任務不得不選擇分配到更遠的節點。
經過在map端對計算結果在緩存中執行聚合和排序,可以節省I/O操做,進而提高系統性能。
AppendOnlyMap和SizeTrackingPairBuffer的容量均可以增加,那麼數據量不大的時候不會有問題。
因爲大數據處理的數據量每每都比較大,所有都放入內存內會將系統內存撐爆,Spark爲了防止這個問題,
提供函數maybeSpillConllection。
wirtePartitionFile用於持久化計算結果。
1.溢出到分區文件後合併:將內存中緩存的多個partition的計算結果分別寫入臨時Block文件,再將這些Block文件的內容所有寫入到Block輸出文件中。
2.內存中排序合併:將緩存的中間計算結果按照partition分組後寫入Block輸出文件。
每一個map任務實際最後只會生成一個磁盤文件。
partitionedIterator 經過對集合按照指定的比較器進行比較,按照partition id分組,生成迭代器。
sendRequest方法用於遠程請求中間結果。
sendRequest利用FetchRequest裏封裝的BlockId、size、address等信息。
調用shuffleClient的fetchBlocks方法獲取其餘節點上的中間結果。
fetchLocalBlock用於對本地中間計算結果的獲取。
本章從迭代計算的層層剝離開始,分析了map和reduce任務的處理邏輯。