整理一些Spark數據傾斜解決的思路

    項目中經常會使用到Spark進行批處理,數據量大的時候總是會遇到數據傾斜的情況,參考了項目中遇到的情況以及網上的一些案例,寫篇文章來總結下如何處理Spark中常見的數據傾斜問題。當然由於業務場景不一樣,本文說到的一些解決數據傾斜的思路肯定不全,如果有更好的方法,方便的話在評論裏也告訴我一下哈。

 

啥叫數據傾斜:

    Spark的RDD由多個Partition組成,如果某個Partition的數據比其他Partition的數據要多很多,這個就是數據傾斜,如下圖所示:

    數據傾斜會導致某個spark任務耗時過長,導致整體任務耗時增加,甚至可能造成OOM。

    數據傾斜大概率是由於HashPartitioner引起的,Range不會,具體可以看我之前寫的《HashPartitioner 與 RangePartitioner》那篇文章。

 

數據傾斜爲什麼會造成OOM:

    在之前分析Shuffle的時候說過,ShuffleWrite端使用的數據結構PartitionedAppendOnlyMap、PartitionedPairBuffer以及ShuffleReader端使用的ExternalAppendOnlyMap、ExternalSorter等等,都會檢查緩存數據的大小,如果太大就會講數據刷寫到磁盤,即理論上應該不會出現OOM。

   個人認爲是由於Spark並非來一條數據就計算一次內存使用大小,那樣太費性能了。Spark使用的是按等比的採樣數量來估算大小,比如第一條、第二條、第四條、第八條..這樣很容易造成估計的內存大小不準確,從而造成OOM。

 

 

數據傾斜如何解決:

1.  過濾掉不用的Key

    有些Key是髒數據,直接過濾掉,這樣可以減少數據量

 

2.  調整並行度

    增大Partition的數量(算子中指定partition數量或者使用reparation算子,不建議自定義partitioner),這樣每個Task要處理的任務就少了,各個key可以均勻的分到多個Partition中。但是如果某個Key的數量就是很多,就不能改變這種問題...

 

3.將Reduce side Join轉變爲Map Side Join

    Spark SQL中自動就有這樣的優化,我們可以借鑑下!

    通過較小的數據的Broadcast出去,將Reduce側Join轉化爲Map側Join,避免Shuffle從而完全消除Shuffle帶來的數據傾斜,這樣shuffle都不會發生,賊6。(ps: 建議groupByKey算子改爲reduceByKey,讓map端也發生agg)

 

4.  隨機前綴擴容 — 進行分階段聚合

    Key之前打個隨機數,然後聚合,在調用算子,這樣可以較少數據量,進行業務計算之後,再進行第二階段的聚合。

    不過得根據業務需求視情況來定,業務接受Key可以分散計算纔行。

 

5. 如果加載數據的時候就發生了數據傾斜,比如使用Spark加載HBase的數據,有些Region的數據量大,有些Region的數據量少。

    可以在加載完之後Region之後進行reparation,或者重寫TableInputFormat,改變加載規則

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