1. 程式人生 > >spark效能調優(三)shuffle的map端記憶體緩衝reduce端記憶體佔比

spark效能調優(三)shuffle的map端記憶體緩衝reduce端記憶體佔比

效能優化 shuffle


spark.shuffle.file.buffer,預設32k
spark.shuffle.memoryFraction,0.2


map端記憶體緩衝,reduce端記憶體佔比;很多資料、網上視訊,都會說,這兩個引數,
是調節shuffle效能的不二選擇,很有效果的樣子,實際上,不是這樣的。


以實際的生產經驗來說,這兩個引數沒有那麼重要,往往來說,shuffle的效能不是因為
這方面的原因導致的


但是,有一點點效果的,broadcast,資料本地化等待時長;這兩個shuffle調優的小點,
其實也是需要跟其他的大量的小點配合起來使用,一點一點的提升效能,最終很多個性能

調優的小點的效果,彙集在一起之後,那麼就會有可以看見的還算不錯的效能調優的效果。


預設情況下,shuffle的map task,輸出到磁碟檔案的時候,統一都會先寫入每個task自己
關聯的一個記憶體緩衝區。


這個緩衝區大小,預設是32kb。


每一次,當記憶體緩衝區滿溢之後,才會進行spill操作,溢寫操作,溢寫到磁碟檔案中去


reduce端task,在拉取到資料之後,會用hashmap的資料格式,來對各個key對應的values進行匯聚。


針對每個key對應的values,執行我們自定義的聚合函式的程式碼,比如_ + _(把所有values累加起來)



reduce task,在進行匯聚、聚合等操作的時候,實際上,使用的就是自己對應的executor的記憶體,
executor(jvm程序,堆),預設executor記憶體中劃分給reduce task進行聚合的比例,是0.2。


問題來了,因為比例是0.2,所以,理論上,很有可能會出現,拉取過來的資料很多,那麼在記憶體中,
放不下;這個時候,預設的行為,就是說,將在記憶體放不下的資料,都spill(溢寫)到磁碟檔案中去。


原理說完之後,來看一下,預設情況下,不調優,可能會出現什麼樣的問題?


預設,map端記憶體緩衝是每個task,32kb。

預設,reduce端聚合記憶體比例,是0.2,也就是20%。


如果map端的task,處理的資料量比較大,但是呢,你的記憶體緩衝大小是固定的。
可能會出現什麼樣的情況?


每個task就處理320kb,32kb,總共會向磁碟溢寫320 / 32 = 10次。
每個task處理32000kb,32kb,總共會向磁碟溢寫32000 / 32 = 1000次。


在map task處理的資料量比較大的情況下,而你的task的記憶體緩衝預設是比較小的,32kb。
可能會造成多次的map端往磁碟檔案的spill溢寫操作,發生大量的磁碟IO,從而降低效能。


reduce端聚合記憶體,佔比。預設是0.2。如果資料量比較大,reduce task拉取過來的資料很多,
那麼就會頻繁發生reduce端聚合記憶體不夠用,頻繁發生spill操作,溢寫到磁碟上去。而且最要命的是,
磁碟上溢寫的資料量越大,後面在進行聚合操作的時候,很可能會多次讀取磁碟中的資料,進行聚合。


預設不調優,在資料量比較大的情況下,可能頻繁地發生reduce端的磁碟檔案的讀寫。


這兩個點之所以放在一起講,是因為他們倆是有關聯的。資料量變大,map端肯定會出點問題;
reduce端肯定也會出點問題;出的問題是一樣的,都是磁碟IO頻繁,變多,影響效能。


調優:


調節map task記憶體緩衝:spark.shuffle.file.buffer,預設32kb(spark 1.3.x不是這個引數,
後面還有一個字尾,kb;spark 1.5.x以後,變了,就是現在這個引數)
調節reduce端聚合記憶體佔比:spark.shuffle.memoryFraction,0.2


在實際生產環境中,我們在什麼時候來調節兩個引數?


看Spark UI,如果你的公司是決定採用standalone模式,那麼很簡單,你的spark跑起來,
會顯示一個Spark UI的地址,4040的埠,進去看,依次點選進去,可以看到,你的每個stage的詳情,
有哪些executor,有哪些task,每個task的shuffle write和shuffle read的量,shuffle的磁碟和記憶體,
讀寫的資料量;如果是用的yarn模式來提交,課程最前面,從yarn的介面進去,點選對應的application,
進入Spark UI,檢視詳情。


如果發現shuffle 磁碟的write和read,很大。這個時候,就意味著最好調節一些shuffle的引數。
進行調優。首先當然是考慮開啟map端輸出檔案合併機制。


調節上面說的那兩個引數。調節的時候的原則。spark.shuffle.file.buffer,每次擴大一倍,
然後看看效果,64,128;spark.shuffle.memoryFraction,每次提高0.1,看看效果。


不能調節的太大,太大了以後過猶不及,因為記憶體資源是有限的,你這裡調節的太大了,
其他環節的記憶體使用就會有問題了。


調節了以後,效果?map task記憶體緩衝變大了,減少spill到磁碟檔案的次數;reduce端聚合記憶體變大了,
減少spill到磁碟的次數,而且減少了後面聚合讀取磁碟檔案的數量。