1. 程式人生 > >Spark專案實戰-troubleshooting之控制shuffle reduce端緩衝大小以避免OOM

Spark專案實戰-troubleshooting之控制shuffle reduce端緩衝大小以避免OOM

一、reduce緩衝機制

如下,我們知道shuffle的map端task是不斷輸出資料的,資料量可能是很大的。 但是其實reduce端的task,並不是等到map端task將屬於自己的那份資料全部寫入磁碟檔案之後再去拉取的。map端寫一點資料,reduce端task就會拉取一小部分資料,立即進行後面的聚合、運算元函式的應用。每次reduece能夠拉取多少資料,就由緩衝buffer來決定。因為拉取過來的資料,都是先放在buffer中的。然後才用後面的executor分配的堆記憶體佔比(0.2)去進行後續的聚合、函式的執行。 

二、reduce端緩衝(buffer),可能會出什麼問題?

預設情況下該buffer的大小是48MB,也許大多數時候,reduce端task一邊拉取一邊計算,不一定一直都會拉滿48M的資料。可能大多數時候,拉取個10M資料就計算掉了,所以大多數時候不會出現什麼問題。但是有的時候,map端的資料量特別大,然後寫出的速度特別快。reduce端所有task拉取的時候,全部達到自己的緩衝的最大極限值,緩衝48M全部填滿。 這個時候,再加上你的reduce端執行的聚合函式的程式碼,可能會建立大量的物件。可能一下子記憶體就撐不住了就會OOM,reduce端的記憶體中,就會發生記憶體溢位的問題。

三、針對上述的可能出現的問題,我們該怎麼來解決呢?

這個時候,就應該減少reduce端task緩衝的大小。寧願多拉取幾次,但是每次同時能夠拉取到reduce端每個task的數量,比較少,就不容易發生OOM記憶體溢位的問題。(比如,可以調節成12M) 在實際生產環境中,我們都是碰到過這種問題的。這是典型的以效能換執行的原理。reduce端緩衝小了,不容易OOM,但是效能一定是有所下降的,你要拉取的次數就多了。就走更多的網路傳輸開銷。

這種時候,只能採取犧牲效能的方式了。spark作業首先第一要義,就是一定要讓它可以跑起來。

reduce端緩衝大小的另外一面,關於效能調優的一面: 假如說,Map端輸出的資料量也不是特別大,然後整個application的資源也特別充足。200個executor、5個cpu core、10G記憶體。 其實可以嘗試去增加這個reduce端緩衝大小的,比如從48M變成96M。那麼這樣的話,每次reduce task能夠拉取的資料量就很大。需要拉取的次數也就變少了。比如原先需要拉取100次,現在只要拉取50次就可以執行完了。 對網路傳輸效能開銷的減少,以及reduce端聚合操作執行的次數的減少都是有幫助的。 最終達到的效果,就應該是效能上的一定程度上的提升。

四、引數設定

SparkConf conf = new SparkConf()
    .set("spark.reducer.maxSizeInFlight", "24");