Spark的UI優化詳解

原文鏈接:https://blog.csdn.net/m0_37657725/article/details/97305919

集羣環境

集羣環境可以看到集羣一個有280G內存,120核數,5個節點

spark-submit  --

啓動命令含義:

   

spark-submit  class  cn.dmp.tools.Bzip2Parquet  \類的main方法所在類
    --master yarn
    --deploy-mode cluster \ 運行模式
    --driver-memory 4g    \ 共280g
    --executor-memory 8g  \ 每個executor使用的內存大小,一臺機器可以有多個executor,
    --executor-cores 4    \ 共120核數
    /root/dmp.jar         \jar 包
    /adloga/biz2/*        \輸入路徑
    /parquet 20 1         \輸出路徑,20:執行20次

& 後臺啓動命令:
第一次測試:executor-cores 4:並行

nohup spark-submit class cn.dmp.tools.Bzip2Parquet --master yarn --deploy-mode cluster --driver-memory 4g --executor-memory 8g --executor-cores 4 /root/dmp.jar  /adloga/biz2/*  /parquet &

觀察sparkUI

1. 發現gc時間不長

2. 一片綠色效果好,紅色序列化時間,沒有shuffle時間,四個程序一起並行(因爲有四個核數)

3. 總共運行時間

 
第二次測試:executor-cores 1,串行

nohup spark-submit class cn.dmp.tools.Bzip2Parquet --master yarn --deploy-mode cluster --driver-memory 4g --executor-memory 8g --executor-cores 1 /root/dmp.jar  /adloga/biz2/*  /parquet &

發現是單線程跑

運行時間

第三次測試:num-executors :executors的數量,8個block,20個executors

nohup spark-submit class cn.dmp.tools.Bzip2Parquet --master yarn --deploy-mode cluster --driver-memory 4g --executor-memory 8g --executor-cores 1  --num-executors 20 /root/dmp.jar  /adloga/biz2/*  /parquet &

結果:有的executors 沒有任務,一個block對應一個task,所以集羣中還是隻有8個executors 在工作

第四次:重新分區

nohup spark-submit class cn.dmp.tools.Bzip2Parquet --master yarn --deploy-mode cluster --driver-memory 4g --executor-memory 8g --executor-cores 1  --num-executors 20 /root/dmp.jar  /adloga/biz2/*  /parquet    20   5 &        

上面20:指分區個數,20個分區一個分區對應一個executors

我們現在5個節點,有20個task,說明一個節點上面有多個executors ,而每個executors 上面會有多個task

重新分區會有shuffle,

 

結果:有的executors會有多個task,

時間:

job有shuffle就一定慢麼? 不一定,因爲並行度也會增加

 

分區數=核數的2倍到3倍
第四次:調整任務數,核數,達到最優

1.

nohup spark-submit class cn.dmp.tools.Bzip2Parquet --master yarn --deploy-mode cluster --driver-memory 4g --executor-memory 4g --executor-cores 2 --num-executors 50 /root/dmp.jar  /adloga/biz2/*  /parquet    300 &       

共120個核數,操作系統 = 4個核數(4*5=20) 所以任務數是300 (2到3倍)

300個patation,每個分區一個核數

num-executors:共280個g,1個executor-memory= 4g(yarn在調度的時候1g),driver = 4g,  280-4=276, 276/5=55.2 所以50個

 

結果:只申請了45個

時間:

並行度:2

nohup spark-submit class cn.dmp.tools.Bzip2Parquet --master yarn --deploy-mode cluster --driver-memory 4g --executor-memory 8g --executor-cores 5 --num-executors 20 /root/dmp.jar  /adloga/biz2/*  /parquet    300 &

分區數時間有限

時間:差別不是很明顯

 
總結:

增加任務的並行度

executor-memory 8g :

(executor-memory  +1) * num-executors <=集羣總的內存大小

總乘積的時候,executor-memory要多加一個g

executor-cores 5:

executor-cores * num-executors <=集羣總的核數

一個executor如果只分配了一個核數,並行度就是1,如果分配了n個核數,那麼並行的最大數量就是n,

num-executors 20 :申請的總的executor數量,executor數量和分區數量成倍數。

partitionNumber:最好是集羣核數的2到3倍

 
相關參數

進入spark安裝目錄的conf目錄
cp spark-defaults.conf.template spark-defaults.conf

1.spark.shuffle.manager=hash #Spark 1.2的默認Shuffle機制從Hash變成了Sort
應用場景:當不需要進行排序且產生的臨時文件不是很多時,性能可能會比sort shuffle要好。

2.spark.shuffle.spill=false  #全程在內存跑,只有在確定內存足夠使用時,纔可以將這個選項設置爲false。
這個參數的默認值是true,用於指定Shuffle過程中如果內存中的數據超過閾值時是否需要將部分數據臨時寫入外部存儲。
3.spark.shuffle.memoryFraction=0.5  #決定了當Shuffle過程中使用的內存達到總內存多少比例的時候開始spill
#這個值默認是0.2。此參數可以適當調大,可以控制在0.4~0.6。可以適當調大此值,可以減少磁盤I/O次數
4.spark.shuffle.blockTransferService=netty #用於在各個Executor之間傳輸Shuffle數據。

5.spark.shuffle.consolidateFiles = true #爲了解決在Hash Based Shuffle過程中產生過多文件的問題,配置爲true,對於同一個Core上運行的Shuffle Map Task不會產生一個新的Shuffle文件而是重用原來的。
6.spark.shuffle.compress=true #對最終寫入本地文件系統的輸出文件進行壓縮
spark.shuffle.spill.compress = true #最終的shuffle輸出文件進行壓縮

#處理的中間結果在spill到本地硬盤時都會進行壓縮,在將中間結果取回進行merge的時候,要進行解壓
#壓縮,省帶寬,但是消耗cpu,兩者需要衡量。(比如集羣普遍使用的是千兆網絡,那麼將這個選項設置爲true可能更合理;如果計算是CPU密集型的,那麼將這個選項設置爲false可能更好。)
優化

1.更好的序列化實現:更換默認的序列化機制,由原生的java序列化變爲kryo,

原因

    java的序列化有兩個問題,一個是性能相對比較低,另外它序列化完二進制的內容長度也比較大,造成網絡傳輸時間拉長
    kryo,比java的序列化快10倍以上。而且生成內容長度也短

實現方式

方法一:修改spark-defaults.conf配置文件

設置: spark.serializer  org.apache.spark.serializer.KryoSerializer     #注意:用空格隔開

方法二:啓動spark-shell或者spark-submit時配置

      --conf spark.serializer=org.apache.spark.serializer.KryoSerializer

方法三:在代碼中

val conf = new SparkConf()

conf.set(“spark.serializer”,“org.apache.spark.serializer.KryoSerializer”)

三種方式實現效果相同,優先級越來越高。

2.配置spark.local.dir=/home/tmp,/home/tmp2;可以創建多個文件夾,每個文件夾都對應一個真實的硬盤。當產生臨時文件發送磁盤I/O時,可以提高性能。

3.慎用collect:1.速度慢,2.內存溢出,會將分散到不同服務器的數據匯聚到一臺服務器,一般可以將結果存儲在HDFS上

4.使用MapPartitions替代map

5.啓用推測執行機制。可以設置spark.speculation  true

開啓後,spark會檢測執行較慢的Task,並複製這個Task在其他節點運行,最後哪個節點先運行完,就用其結果,然後將慢Task 殺死

6.GC調優,spark是一種高度依賴內存的框架,針對GC調優也很重要,可以看一下這篇文章:垃圾(GC)回收機制及算法以及配置調優

總結

對於大量依賴於內存計算的Spark應用,GC調優顯得尤爲重要。在發現GC問題的時候,不要着急調試GC。而是先考慮是否存在Spark進程內存管理的效率問題,例如RDD緩存的持久化和釋放。至於GC參數的調試,首先我們比較推薦使用G1 GC來運行Spark應用。相較於傳統的垃圾收集器,隨着G1的不斷成熟,需要配置的選項會更少,能同時滿足高吞吐量和低延遲的尋求。當然,GC的調優不是絕對的,不同的應用會有不同應用的特性,掌握根據GC日誌進行調優的方法,才能以不變應萬變。最後,也不能忘了先對程序本身的邏輯和代碼編寫進行考量,例如減少中間變量的創建或者複製,控制大對象的創建,將長期存活對象放在Off-heap中等等。
 ————————————————
版權聲明:本文爲CSDN博主「靜靜七分醉」的原創文章,遵循CC 4.0 by-sa版權協議,轉載請附上原文出處鏈接及本聲明。
原文鏈接:https://blog.csdn.net/m0_37657725/article/details/97305919

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