Spark面試題(五)——數據傾斜調優

Spark面試題系列

1、數據傾斜

數據傾斜指的是,並行處理的數據集中,某一部分(如Spark或Kafka的一個Partition)的數據顯著多於其它部分,從而使得該部分的處理速度成爲整個數據集處理的瓶頸。
數據傾斜倆大直接致命後果
1、數據傾斜直接會導致一種情況:Out Of Memory。
2、運行速度慢。
主要是發生在Shuffle階段。同樣Key的數據條數太多了。導致了某個key(下圖中的80億條)所在的Task數據量太大了。遠遠超過其他Task所處理的數據量。

數據傾斜

一個經驗結論是:一般情況下,OOM的原因都是數據傾斜

2、如何定位數據傾斜

數據傾斜一般會發生在shuffle過程中。很大程度上是你使用了可能會觸發shuffle操作的算子:distinct、groupByKey、reduceByKey、aggregateByKey、join、cogroup、repartition等。
原因:查看任務->查看Stage->查看代碼
某個task執行特別慢的情況
某個task莫名其妙內存溢出的情況
查看導致數據傾斜的key的數據分佈情況

定位數據傾斜

也可從以下幾種情況考慮:
1、是不是有OOM情況出現,一般是少數內存溢出的問題
2、是不是應用運行時間差異很大,總體時間很長
3、需要了解你所處理的數據Key的分佈情況,如果有些Key有大量的條數,那麼就要小心數據傾斜的問題
4、一般需要通過Spark Web UI和其他一些監控方式出現的異常來綜合判斷
5、看看代碼裏面是否有一些導致Shuffle的算子出現

3、數據傾斜的幾種典型情況

3.1 數據源中的數據分佈不均勻,Spark需要頻繁交互
3.2 數據集中的不同Key由於分區方式,導致數據傾斜
3.3 JOIN操作中,一個數據集中的數據分佈不均勻,另一個數據集較小(主要)
3.4 聚合操作中,數據集中的數據分佈不均勻(主要)
3.5 JOIN操作中,兩個數據集都比較大,其中只有幾個Key的數據分佈不均勻
3.6 JOIN操作中,兩個數據集都比較大,有很多Key的數據分佈不均勻
3.7 數據集中少數幾個key數據量很大,不重要,其他數據均勻

注意:
1、需要處理的數據傾斜問題就是Shuffle後數據的分佈是否均勻問題
2、只要保證最後的結果是正確的,可以採用任何方式來處理數據傾斜,只要保證在處理過程中不發生數據傾斜就可以

4、數據傾斜的處理方法

4.1 數據源中的數據分佈不均勻,Spark需要頻繁交互

解決方案:避免數據源的數據傾斜
實現原理:通過在Hive中對傾斜的數據進行預處理,以及在進行kafka數據分發時儘量進行平均分配。這種方案從根源上解決了數據傾斜,徹底避免了在Spark中執行shuffle類算子,那麼肯定就不會有數據傾斜的問題了。
方案優點:實現起來簡單便捷,效果還非常好,完全規避掉了數據傾斜,Spark作業的性能會大幅度提升。
方案缺點:治標不治本,Hive或者Kafka中還是會發生數據傾斜。
適用情況:在一些Java系統與Spark結合使用的項目中,會出現Java代碼頻繁調用Spark作業的場景,而且對Spark作業的執行性能要求很高,就比較適合使用這種方案。將數據傾斜提前到上游的Hive ETL,每天僅執行一次,只有那一次是比較慢的,而之後每次Java調用Spark作業時,執行速度都會很快,能夠提供更好的用戶體驗。
總結:前臺的Java系統和Spark有很頻繁的交互,這個時候如果Spark能夠在最短的時間內處理數據,往往會給前端有非常好的體驗。這個時候可以將數據傾斜的問題拋給數據源端,在數據源端進行數據傾斜的處理。但是這種方案沒有真正的處理數據傾斜問題。

4.2 數據集中的不同Key由於分區方式,導致數據傾斜

解決方案1:調整並行度
實現原理:增加shuffle read task的數量,可以讓原本分配給一個task的多個key分配給多個task,從而讓每個task處理比原來更少的數據。
方案優點:實現起來比較簡單,可以有效緩解和減輕數據傾斜的影響。
方案缺點:只是緩解了數據傾斜而已,沒有徹底根除問題,根據實踐經驗來看,其效果有限。
實踐經驗:該方案通常無法徹底解決數據傾斜,因爲如果出現一些極端情況,比如某個key對應的數據量有100萬,那麼無論你的task數量增加到多少,都無法處理。

4.2 數據集中的不同Key由於分區方式,導致數據傾斜

總結:調整並行度:適合於有大量key由於分區算法或者分區數的問題,將key進行了不均勻分區,可以通過調大或者調小分區數來試試是否有效

解決方案2:
緩解數據傾斜(自定義Partitioner)
適用場景:大量不同的Key被分配到了相同的Task造成該Task數據量過大。
解決方案: 使用自定義的Partitioner實現類代替默認的HashPartitioner,儘量將所有不同的Key均勻分配到不同的Task中。
優勢: 不影響原有的並行度設計。如果改變並行度,後續Stage的並行度也會默認改變,可能會影響後續Stage。
劣勢: 適用場景有限,只能將不同Key分散開,對於同一Key對應數據集非常大的場景不適用。效果與調整並行度類似,只能緩解數據傾斜而不能完全消除數據傾斜。而且需要根據數據特點自定義專用的Partitioner,不夠靈活。

4.3 JOIN操作中,一個數據集中的數據分佈不均勻,另一個數據集較小(主要)

解決方案:Reduce side Join轉變爲Map side Join
方案適用場景:在對RDD使用join類操作,或者是在Spark SQL中使用join語句時,而且join操作中的一個RDD或表的數據量比較小(比如幾百M),比較適用此方案。
方案實現原理:普通的join是會走shuffle過程的,而一旦shuffle,就相當於會將相同key的數據拉取到一個shuffle read task中再進行join,此時就是reduce join。但是如果一個RDD是比較小的,則可以採用廣播小RDD全量數據+map算子來實現與join同樣的效果,也就是map join,此時就不會發生shuffle操作,也就不會發生數據傾斜。
方案優點:對join操作導致的數據傾斜,效果非常好,因爲根本就不會發生shuffle,也就根本不會發生數據傾斜。
方案缺點:適用場景較少,因爲這個方案只適用於一個大表和一個小表的情況。

4.4 聚合操作中,數據集中的數據分佈不均勻(主要)

解決方案:兩階段聚合(局部聚合+全局聚合)
適用場景:對RDD執行reduceByKey等聚合類shuffle算子或者在Spark SQL中使用group by語句進行分組聚合時,比較適用這種方案
實現原理:將原本相同的key通過附加隨機前綴的方式,變成多個不同的key,就可以讓原本被一個task處理的數據分散到多個task上去做局部聚合,進而解決單個task處理數據量過多的問題。接着去除掉隨機前綴,再次進行全局聚合,就可以得到最終的結果。具體原理見下圖。
優點:對於聚合類的shuffle操作導致的數據傾斜,效果是非常不錯的。通常都可以解決掉數據傾斜,或者至少是大幅度緩解數據傾斜,將Spark作業的性能提升數倍以上。
缺點:僅僅適用於聚合類的shuffle操作,適用範圍相對較窄。如果是join類的shuffle操作,還得用其他的解決方案將相同key的數據分拆處理

4.4 聚合操作中,數據集中的數據分佈不均勻

4.5 JOIN操作中,兩個數據集都比較大,其中只有幾個Key的數據分佈不均勻

解決方案:爲傾斜key增加隨機前/後綴
適用場景:兩張表都比較大,無法使用Map側Join。其中一個RDD有少數幾個Key的數據量過大,另外一個RDD的Key分佈較爲均勻。
解決方案:將有數據傾斜的RDD中傾斜Key對應的數據集單獨抽取出來加上隨機前綴,另外一個RDD每條數據分別與隨機前綴結合形成新的RDD(笛卡爾積,相當於將其數據增到到原來的N倍,N即爲隨機前綴的總個數),然後將二者Join後去掉前綴。然後將不包含傾斜Key的剩餘數據進行Join。最後將兩次Join的結果集通過union合併,即可得到全部Join結果。
優勢:相對於Map側Join,更能適應大數據集的Join。如果資源充足,傾斜部分數據集與非傾斜部分數據集可並行進行,效率提升明顯。且只針對傾斜部分的數據做數據擴展,增加的資源消耗有限。
劣勢:如果傾斜Key非常多,則另一側數據膨脹非常大,此方案不適用。而且此時對傾斜Key與非傾斜Key分開處理,需要掃描數據集兩遍,增加了開銷。
注意:具有傾斜Key的RDD數據集中,key的數量比較少

4.5 JOIN操作中,兩個數據集都比較大,其中只有幾個Key的數據分佈不均勻

4.6 JOIN操作中,兩個數據集都比較大,有很多Key的數據分佈不均勻

解決方案:隨機前綴和擴容RDD進行join
適用場景:如果在進行join操作時,RDD中有大量的key導致數據傾斜,那麼進行分拆key也沒什麼意義。
實現思路:將該RDD的每條數據都打上一個n以內的隨機前綴。同時對另外一個正常的RDD進行擴容,將每條數據都擴容成n條數據,擴容出來的每條數據都依次打上一個0~n的前綴。最後將兩個處理後的RDD進行join即可。和上一種方案是儘量只對少數傾斜key對應的數據進行特殊處理,由於處理過程需要擴容RDD,因此上一種方案擴容RDD後對內存的佔用並不大;而這一種方案是針對有大量傾斜key的情況,沒法將部分key拆分出來進行單獨處理,因此只能對整個RDD進行數據擴容,對內存資源要求很高。
優點:對join類型的數據傾斜基本都可以處理,而且效果也相對比較顯著,性能提升效果非常不錯。
缺點:該方案更多的是緩解數據傾斜,而不是徹底避免數據傾斜。而且需要對整個RDD進行擴容,對內存資源要求很高。
實踐經驗:曾經開發一個數據需求的時候,發現一個join導致了數據傾斜。優化之前,作業的執行時間大約是60分鐘左右;使用該方案優化之後,執行時間縮短到10分鐘左右,性能提升了6倍。
注意:將傾斜Key添加1-N的隨機前綴,並將被Join的數據集相應的擴大N倍(需要將1-N數字添加到每一條數據上作爲前綴)

4.6 JOIN操作中,兩個數據集都比較大,有很多Key的數據分佈不均勻

4.7 數據集中少數幾個key數據量很大,不重要,其他數據均勻

解決方案:過濾少數傾斜Key
適用場景:如果發現導致傾斜的key就少數幾個,而且對計算本身的影響並不大的話,那麼很適合使用這種方案。比如99%的key就對應10條數據,但是隻有一個key對應了100萬數據,從而導致了數據傾斜。
優點:實現簡單,而且效果也很好,可以完全規避掉數據傾斜。
缺點:適用場景不多,大多數情況下,導致傾斜的key還是很多的,並不是只有少數幾個。
實踐經驗:在項目中我們也採用過這種方案解決數據傾斜。有一次發現某一天Spark作業在運行的時候突然OOM了,追查之後發現,是Hive表中的某一個key在那天數據異常,導致數據量暴增。因此就採取每次執行前先進行採樣,計算出樣本中數據量最大的幾個key之後,直接在程序中將那些key給過濾掉。

猜你喜歡
Hive計算最大連續登陸天數
Hadoop 數據遷移用法詳解
Hbase修復工具Hbck
數倉建模分層理論
一文搞懂Hive的數據存儲與壓縮
大數據組件重點學習這幾個

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