Spark 5. Shuffle 操作 (官方編程指南翻譯)

Shuffle 操作 (官方編程指南翻譯)

原文地址: http://spark.apache.org/docs/latest/programming-guide.html#shuffle-operations
文章僅限交流使用,轉(zhuǎn)載請(qǐng)注明出處。如有錯(cuò)誤,歡迎指出!

Henvealf/譯

在 Spark 觸發(fā)一個(gè)事件的時(shí)確定無疑的發(fā)生的操作就叫做 shuffle 。Shuffle 是 Spark 重建數(shù)據(jù)的機(jī)制,來將來自不同分區(qū)的數(shù)據(jù)進(jìn)行分組。典型的麻煩就是需要在執(zhí)行器和機(jī)器之間進(jìn)行數(shù)據(jù)拷貝,是 shuffle 中一個(gè)復(fù)雜并且大開銷的操作。

背景

為了理解 shuffle 過程中發(fā)生了什么,我們可以考慮一下 reduceByKey 操作。 reduceByKey 操作會(huì)將相同key中的值聚合進(jìn)一個(gè)元祖中而生成一個(gè)新的 RDD -- 值的合并操作是依賴于key的。這里的挑戰(zhàn)就是在 key 中,并不是所有值都被分在了一個(gè)分區(qū)里,或者說不是在相同的機(jī)器里,但是他們必須要放在一個(gè)地方才能計(jì)算出結(jié)果。

在 Spark 中, 對(duì)于指定的操作,數(shù)據(jù)在一般情況下不是按照分區(qū)來分布到必要的地方。在計(jì)算過程中,一個(gè)單獨(dú)的任務(wù)將會(huì)在一個(gè)單獨(dú)的分區(qū)上操作,事實(shí)上,如果將所有的數(shù)據(jù)組織在一個(gè)單獨(dú)的 reduceByKey 匯合任務(wù)上去執(zhí)行的話,Spark 需要去執(zhí)行一個(gè)多對(duì)多(all-to-all,多個(gè)task與多個(gè)分區(qū)?)的操作.他必須從所有的分區(qū)中為每一個(gè) key 尋找他們的 values,然后跨越分區(qū)將同key的值帶到一起去計(jì)算最后的結(jié)果--這個(gè)過程就叫做 shuffle。

盡管在經(jīng)歷了shuffle數(shù)據(jù)之后的每個(gè)分區(qū)中的元素是確定的,但分區(qū)內(nèi)部自己進(jìn)行排序,所以他們的元素的也能是無順序的。如果想要在 shuffle 后希望是有序的,使用下面的方式就能做到:

  • mapPartitions 使用像 sorted 一樣的方法去排序每個(gè)分區(qū)。
  • 當(dāng)重新分區(qū)的同時(shí)可以使用 repartitionAndSortWithinPartitions 來對(duì)分區(qū)進(jìn)行快速的排序。
  • sordBy 可一全局的排序一整個(gè) RDD。

想 repartition 和 coalesce 這種重新分區(qū)的操作,groupByKey 和 reduceByKey 這種 ‘ByKey’ 操作 和 cogroup 和 join 這種 join 操作也都會(huì)觸發(fā) shuffle,

效率影響

Shuffle 是一個(gè)開銷很大的操作,他會(huì)同時(shí)用到 磁盤讀寫,數(shù)據(jù)序列化以及網(wǎng)絡(luò)讀寫。為了為 shuffle操作組織數(shù)據(jù), Spark 會(huì)產(chǎn)生 -map 與 -reduce 兩種任務(wù),是從 MapReduce 中得來的名詞,與 Spark 中 map 與 reduce 函數(shù)不是同一個(gè)東西。

內(nèi)建的情況下, 從 map 任務(wù)生成的結(jié)果會(huì)一直放在內(nèi)存中,直到內(nèi)存放不下。然后,數(shù)據(jù)會(huì)基于分區(qū)進(jìn)行排序,然后寫進(jìn)一個(gè)文件中。在 reduce 端,就直接讀取與之相關(guān)的已經(jīng)排序好的塊。
確定的 shuffle 操作能夠消費(fèi)客觀數(shù)量的堆內(nèi)存,在傳輸記錄之后,他使用的是內(nèi)存中的數(shù)據(jù)結(jié)構(gòu)來組織這些記錄。特別的,reduceByKey 和 aggregateByKey 在 map 端創(chuàng)建這些結(jié)構(gòu)和 ByKey操作在 reduce 端產(chǎn)生他們(??)。如果數(shù)據(jù)在內(nèi)存中放不小了,就放入磁盤中并增強(qiáng)垃圾收集。

Shuffle 也會(huì)在磁盤上產(chǎn)生大量的中間文件。像 Spark 1.3,直到相應(yīng)的 RDD 不在被使用和垃圾收集,這些文件會(huì)一直保存著。所以如果 lineage 沒有被重新運(yùn)算, shuffle 文件就不需要重建了。如果應(yīng)用程序維持著對(duì)著些 RDD 的引用或者 GC 內(nèi)有頻繁的 kick,垃圾收集可能會(huì)經(jīng)過很長的周期才發(fā)生。這意味著一個(gè)需要運(yùn)行很長時(shí)間的 Spark job 與需要消耗大量的磁盤空間。中間文件的存儲(chǔ)路徑在配置 Spark context 的時(shí)候使用 spark.local.dir 來指定。

Shuffle行為能夠使用各種各樣的配置參數(shù)來調(diào)節(jié)。詳細(xì)請(qǐng)看 Spark Configuration Guide 的 Shuffle Behavior 章節(jié)。

End!!

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

推薦閱讀更多精彩內(nèi)容