spark-24.spark調優_2_spark的數據傾斜

1.什麼是數據傾斜

數據傾斜指的是,並行處理的數據集中,某一部分(如Spark或Kafka的一個Partition)的數據顯著多於其它部分,從而使得該部分的處理速度成爲整個數據集處理的瓶頸。
數據傾斜在spark中將導致兩個嚴重的後果:

  1. 數據傾斜直接會導致一種情況:Out Of Memory。
  2. 運行速度慢。
    一個經驗性的結論是:一般情況下,OOM的原因都是數據傾斜。

2.如何定位數據傾斜

數據傾斜一般會發生在Shuffle過程中,很大程度上是你使用了可能會觸發Shuffle操作的算子:
distinct\ groupByKey \ reduceByKey \ aggregateByKey \ join \ cogroup \ repartition等。

  • 某個task執行的特別慢的情況:通過history UI 來查看,任務-》查看stage-》查看代碼。
  • 某個task莫名其妙內存溢出的情況:多試幾次,看是否能通過資源的調整來解決問題,並結合history UI 來進行查看和分析。
  • 查看導致導致數據傾斜的key的數據分佈情況:主要通過抽樣的方式來獲知目前key的分佈情況,根據業務邏輯制定相應的解決fangan。

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

數據源中的數據分佈不均勻,Spark需要頻繁交互。
數據集中的不同key由於分區方式,導致數據傾斜。
JOIN操作中,一個數據集中的數據分佈不均勻,另一個數據集較小。
聚合操作中,數據集中的數據分佈不均勻。
JOIN操作中,兩個數據集都比較大,其中只有幾個key的數據分佈不均勻。
JOIN操作中,兩個數據集都比較大,有很多key的數據分佈不均勻。
數據集中少數幾個key數據量很大,不重要,其它數據均勻。

1.緩解數據傾斜-避免數據源的數據傾斜:

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

2.緩解數據傾斜-調整並行度:

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

3.緩解數據傾斜 -自定義Partitioner:

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

4.緩解數據傾斜 - 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,也就根本不會發生數據傾斜。
  • 方案缺點:
    適用場景較少,因爲這個方案只適用於一個大表和一個小表的情況。
    在這裏插入圖片描述

5.緩解數據傾斜 - 兩階段聚合(局部聚合+全局聚合):

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

6.緩解數據傾斜 – 爲傾斜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的分佈。
    在這裏插入圖片描述

7.緩解數據傾斜 -隨機前綴和擴容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倍。
    在這裏插入圖片描述

8.緩解數據傾斜 – 過濾少數傾斜Key:

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