spark關於數據傾斜問題

spark的數據傾斜調優方案歸納總結:

不來虛的,直接上解決方法。

數據傾斜產生原因:在運算過程中把數據分配給不同的Task,一般需要Shuffle過程,同一個Key都會交給Task處理,但是有時同一個Key的values數據量太多造成數據堆積等。

判斷是否發生數據傾斜:通過Web UI查看Task的metrics某些Task相當於其他大多數Task來說所消耗相當長的時間。

數據傾斜解決方案:

(1)對源數據進行聚合並過濾掉導致傾斜的Keys

對源數據進行聚合並過濾掉導致傾斜的keys:數據源記錄中導致數據傾斜的Key可能只有幾個,這些Key不影響業務的計算,匯聚後對應的Value值卻很多,可能導致數據傾斜。

    1. 可使用filter算子過濾掉傾斜的Key值;
    2. 若使用Hive工具,可以將數據傾斜的操作前移到Hive中進行,在Hive中對數據傾斜進行預處理,從數據根源上解決數據傾斜;
    3. 若在Spark SQL中發生傾斜,可使用where/filter算子過濾,然後再進行groupBy等操作。或採用sample算子,對DataFrame的Key值採樣,若不是業務需要,使用where/filter直接過濾掉。

(2)適當提高Reducer端的並行度(並行度指的是RDD的分區數)。

改善並行度之所以改變數據傾斜的原因:若某個Task有100個Key且數據量特別大,就有可能導致OOM(Out Of Memory)或任務運行特別慢,若把並行度調大,則可分解該Task的數據量。

2.1對於reduceByKey可傳入並行度參數numPartitions: Int,該參數設置了shuffle算子執行Shuffle read Task的數量;

2.2 亦可自定義Partitioner,增加Executor改變計算資源。

(3)使用隨機Key實現雙重聚合

隨機Key雙重集合:指Spark分佈式計算對RDD調用reduceByKey各算子,使用對Key值隨機數前綴的處理技巧,對Key值進行二次聚合。第一次聚合(局部聚合)是對每個Key值加上一個隨機數,執行第一次reduceByKey聚合操作;第二次聚合(雙重聚合)是指去掉Key值的前綴隨機數,執行第二次reduceByKey聚合,得到最終結果。

原理:使用隨機Key實現雙重聚合,原理剖析算子reduceByKey。假設有數據傾斜,則給所有的Key加上一個隨機數,然後進行reduceByKey操作,原來非常大的傾斜的Key就分而治之變成若干個較小的Key,不過此時結果和原來不一樣,則使用map操作把隨機數前綴去掉,然後再次進行reduceByKey操作。

注意事項:使用隨機Key雙重聚合侷限於單個RDD的reduceByKey、groupByKey等算子。若兩個RDD的數據量都特別大,而且傾斜的Key特別多,就無法使用隨機Key雙重聚合方案。

(4)使用Mapper端進行join操作

把Reducer端的操作放在Mapper端執行,就避免了Shuffle,很大程度上化解掉了數據傾斜問題。RDD是鏈式操作,DAGScheduler根絕RDD的不同類型的依賴關係(寬依賴和窄依賴)劃分成不同的Stage,當發生寬依賴時把Stage劃分成更小的Stage,寬依賴算子如reduceByKey、groupByKey等,在Mapper端進行join操作就是把寬依賴減掉,避免shuffle操作。

場景應用:若兩個RDD進行操作,其中一個RDD數據量較小,就把此RDD的數據以廣播變量的形式散發給各個Executor,這樣就可與另一個RDD進行map操作了。

條件:要進行join的RDD,其中一個RDD數據量比較小。

(5)對傾斜Keys採樣後進行單獨的join操作

若果兩個RDD的數據量都比較大,則考慮使用採樣方案。

在spark中可直接使用採樣算法sample找出哪個RDD導致數據傾斜,sample算法採樣一般不超過原數據的30%

對傾斜的Keys進行採樣步驟:

RDD1和RDD2進行join操作,採用採樣的方式返現RDD1有嚴重的數據傾斜的Key。

第一步:採用RDD提供的採樣接口,對RDD1全部原數據進行採樣,然後基於採樣的數據可以計算出哪些Key的Values值最多;

第二步:把全部數據分爲兩部分RDD11和RDD12,RDD11代表導致傾斜的Key,RDD12是不會發生數據傾斜的Key;

第三步:RDD11和RDD12分別於RDD2進行join操作,然後把join的結果進行union操作,從而得出RDD1與RDD2直接join的結果。

原理:RDD12與RDD2進行join操作不會發生數據傾斜,因爲兩個RDD中的Key的Values值都不多,RDD11和RDD2進行join操作,利用spark core的並行機制對RDD11的Key的數據進行拆分。

注意事項:對RDD1進行sample採樣計算出一個結果,採樣後進行map操作,通過reduceByKey操作計數,然後對Key和Value進行置換,通過SortByKey進行排序,再進行map置換操作,從而找出哪個Key值傾斜嚴重,對其進行過濾,提取到RDD11中,沒有發生傾斜的提取到RDD12中。

(6)使用隨機數進行join

傾斜的Key加上隨機數:對Key進行map操作加上隨機數,計算結果後再次進行map操作,將隨機數去掉,這樣得到的結果與不加隨機數的結果是一樣的,好處是可控制並行度。

使用隨機數的步驟:

第一步:對RDD1使用mapToPair算子進行轉換,使用Random random = new Random();構建一個隨機數,如任意一個100以內的隨機數random.nextInt(100)賦值給prefix,將prefix與Key值拼接成一個新的Key值:prefix_Key;

第二步:對RDD2使用mapToPair算子進行轉換,對於RDD1相同的Key值,同樣構建隨機數加上前綴,也將prefix加上Key值拼接成新的key值:prefix_Key;

第三步:RDD1和RDD2根絕prefix_Key進行join操作;

第四步:RDD1和RDD2進行join的結果再次map算子轉換,去掉隨機數,得到最終結果。

使用場景:兩個RDD的某一個Key或多個key值的數據量特別大,在進行join等操作時發生數據傾斜,必須知道哪些Keys的值發生傾斜。

(7)通過擴容進行join

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章