spark並行度設置及submit參數

–spark submit

spark-submit --conf spark.default.parallelism=40 --num-executors 5 --executor-cores 4 --executor-memory 8G --master yarn --class com.xx.TopDiscount topnDiscount-1.0-SNAPSHOT.jar $1 $2

spark-submit --conf spark.default.parallelism=12 --num-executors 3 --executor-cores 2 --executor-memory 2G --master yarn --class com.heroking.spark.WordCount spark-word-count.jar

1.Spark的並行度指的是什麼?
spark作業中,各個stage的task的數量,也就代表了spark作業在各個階段stage的並行度!
當分配完所能分配的最大資源了,然後對應資源去調節程序的並行度,如果並行度沒有與資源相匹配,那麼導致你分配下去的資源都浪費掉了。同時並行運行,還可以讓每個task要處理的數量變少(很簡單的原理。合理設置並行度,可以充分利用集羣資源,減少每個task處理數據量,而增加性能加快運行速度。)

舉例:
假如, 現在已經在spark-submit 腳本里面,給我們的spark作業分配了足夠多的資源,比如50個executor ,每個executor 有10G內存,每個executor有3個cpu core 。 基本已經達到了集羣或者yarn隊列的資源上限。
task沒有設置,或者設置的很少,比如就設置了,100個task 。 50個executor ,每個executor 有3個core ,也就是說
Application 任何一個stage運行的時候,都有總數150個cpu core ,可以並行運行。但是,你現在只有100個task ,平均分配一下,每個executor 分配到2個task,ok,那麼同時在運行的task,只有100個task,每個executor 只會並行運行 2個task。 每個executor 剩下的一個cpu core 就浪費掉了!你的資源,雖然分配充足了,但是問題是, 並行度沒有與資源相匹配,導致你分配下去的資源都浪費掉了。合理的並行度的設置,應該要設置的足夠大,大到可以完全合理的利用你的集羣資源; 比如上面的例子,總共集羣有150個cpu core ,可以並行運行150個task。那麼你就應該將你的Application 的並行度,至少設置成150個,才能完全有效的利用你的集羣資源,讓150個task ,並行執行,而且task增加到150個以後,即可以同時並行運行,還可以讓每個task要處理的數量變少; 比如總共 150G 的數據要處理, 如果是100個task ,每個task 要計算1.5G的數據。 現在增加到150個task,每個task只要處理1G數據。

2.如何去提高並行度?
1、task數量,至少設置成與spark Application 的總cpu core 數量相同(最理性情況,150個core,分配150task,一起運行,差不多同一時間運行完畢)官方推薦,task數量,設置成spark Application 總cpu core數量的2~3倍 ,比如150個cpu core ,基本設置 task數量爲 300~ 500. 與理性情況不同的,有些task 會運行快一點,比如50s 就完了,有些task 可能會慢一點,要一分半才運行完,所以如果你的task數量,剛好設置的跟cpu core 數量相同,可能會導致資源的浪費,因爲 比如150task ,10個先運行完了,剩餘140個還在運行,但是這個時候,就有10個cpu core空閒出來了,導致浪費。如果設置2~3倍,那麼一個task運行完以後,另外一個task馬上補上來,儘量讓cpu core不要空閒。同時儘量提升spark運行效率和速度。提升性能。

2、如何設置一個Spark Application的並行度?

  spark.defalut.parallelism   默認是沒有值的,如果設置了值比如說10,是在shuffle的過程纔會起作用(val rdd2 = rdd1.reduceByKey(_+_) //rdd2的分區數就是10,rdd1的分區數不受這個參數的影響)

  new SparkConf().set(“spark.defalut.parallelism”,”“500)

3、如果讀取的數據在HDFS上,增加block數,默認情況下split與block是一對一的,而split又與RDD中的partition對應,所以增加了block數,也就提高了並行度。
4、RDD.repartition,給RDD重新設置partition的數量
5、reduceByKey的算子指定partition的數量
val rdd2 = rdd1.reduceByKey(+,10) val rdd3 = rdd2.map.filter.reduceByKey(+)
6、val rdd3 = rdd1.join(rdd2) rdd3裏面partiiton的數量是由父RDD中最多的partition數量來決定,因此使用join算子的時候,增加父RDD中partition的數量。
7、spark.sql.shuffle.partitions //spark sql中shuffle過程中partitions的數量

–num-executors
該參數主要用於設置該應用總共需要多少executors來執行,Driver在向集羣資源管理器申請資源時需要根據此參數決定分配的Executor個數,並儘量滿足所需。在不帶的情況下只會分配少量Executor。這個值得設置還是要看分配的隊列的資源情況,太少了無法充分利用集羣資源,太多了則難以分配需要的資源。

–executor-memory
設置每個executor的內存,對Spark作業運行的性能影響很大。一般4-8G就差不多了,當然還要看資源隊列的情況。num-executor*executor-memory的大小絕不能超過隊列的內存總大小,保險起見不能超過隊列總大小的2/3,因爲還有一些調度任務或其它spark任務

–executor-cores
設置每個executor的cpu核數,其決定了每個executor並行執行task的能力。Executor的CPU core數量設置爲2-4個即可。但要注意,num-executor*executor-cores也不能超過分配隊列中cpu核數的大小,保險起見不能超過隊列總大小的2/3,因爲還有一些調度任務或其它spark任務。具體的核數的設置需要根據分配隊列中資源統籌考慮,取得Executor,核數,及任務數的平衡。對於多任務共享的隊列,更要注意不能將資源佔滿

–driver-memory
運行sparkContext的Driver所在所佔用的內存,通常不必設置,設置的話1G就足夠了,除非是需要使用collect之類算子經常需要將數據提取到driver中的情況。
–total-executor-cores
是所有executor總共使用的cpu核數 standalone default all cores,一般大公司的集羣會有限制不會允許一個任務把資源都用完

–conf

–conf spark.default.parallelism
此參數用於設置每個stage經TaskScheduler進行調度時生成task的數量,此參數未設置時將會根據讀到的RDD的分區生成task,即根據源數據在hdfs中的分區數確定,若此分區數較小,則處理時只有少量task在處理,前述分配的executor中的core大部分無任務可幹。通常可將此值設置爲num-executors*executor-cores的2-3倍爲宜,如果與其相近的話,則對於先完成task的core則無任務可幹。2-3倍數量關係的話即不至於太零散,又可是的任務執行更均衡。!!個人建議配置該參數

–conf spark.storage.memoryFraction
參數說明:該參數用於設置RDD持久化數據在Executor內存中能佔的比例,默認是0.6。也就是說,默認Executor 60%的內存,可以用來保存持久化的RDD數據。根據你選擇的不同的持久化策略,如果內存不夠時,可能數據就不會持久化,或者數據會寫入磁盤。
參數調優建議:如果Spark作業中,有較多的RDD持久化操作,該參數的值可以適當提高一些,保證持久化的數據能夠容納在內存中。避免內存不夠緩存所有的數據,導致數據只能寫入磁盤中,降低了性能。但是如果Spark作業中的shuffle類操作比較多,而持久化操作比較少,那麼這個參數的值適當降低一些比較合適。此外,如果發現作業由於頻繁的gc導致運行緩慢(通過spark web ui可以觀察到作業的gc耗時),意味着task執行用戶代碼的內存不夠用,那麼同樣建議調低這個參數的值。個人不太建議調該參數

–conf spark.shuffle.memoryFraction
參數說明:該參數用於設置shuffle過程中一個task拉取到上個stage的task的輸出後,進行聚合操作時能夠使用的Executor內存的比例,默認是0.2。也就是說,Executor默認只有20%的內存用來進行該操作。shuffle操作在進行聚合時,如果發現使用的內存超出了這個20%的限制,那麼多餘的數據就會溢寫到磁盤文件中去,此時就會極大地降低性能。
參數調優建議:如果Spark作業中的RDD持久化操作較少,shuffle操作較多時,建議降低持久化操作的內存佔比,提高shuffle操作的內存佔比比例,避免shuffle過程中數據過多時內存不夠用,必須溢寫到磁盤上,降低了性能。此外,如果發現作業由於頻繁的gc導致運行緩慢,意味着task執行用戶代碼的內存不夠用,那麼同樣建議調低這個參數的值。個人不太建議調該參數

–conf spark.sql.codegen
默認值爲false,當它設置爲true時,Spark SQL會把每條查詢的語句在運行時編譯爲java的二進制代碼。這有什麼作用呢?它可以提高大型查詢的性能,但是如果進行小規模的查詢的時候反而會變慢,就是說直接用查詢反而比將它編譯成爲java的二進制代碼快。所以在優化這個選項的時候要視情況而定。
這個選項可以讓Spark SQL把每條查詢語句在運行前編譯爲java二進制代碼,由於生成了專門運行指定查詢的代碼,codegen可以讓大型查詢或者頻繁重複的查詢明顯變快,然而在運行特別快(1-2秒)的即時查詢語句時,codegen就可能增加額外的開銷(將查詢語句編譯爲java二進制文件)。codegen還是一個實驗性的功能,但是在大型的或者重複運行的查詢中使用codegen

–conf spark.sql.inMemoryColumnStorage.compressed
默認值爲false 它的作用是自動對內存中的列式存儲進行壓縮

–conf spark.sql.inMemoryColumnStorage.batchSize
默認值爲1000 這個參數代表的是列式緩存時的每個批處理的大小。如果將這個值調大可能會導致內存不夠的異常,所以在設置這個的參數的時候得注意你的內存大小
在緩存SchemaRDD(Row RDD)時,Spark SQL會安照這個選項設定的大小(默認爲1000)把記錄分組,然後分批次壓縮。
太小的批處理會導致壓縮比過低,而太大的話,比如當每個批處理的數據超過內存所能容納的大小時,也有可能引發問題。
如果你表中的記錄比價大(包含數百個字段或者包含像網頁這樣非常大的字符串字段),就可能需要調低批處理的大小來避免內存不夠(OOM)的錯誤。如果不是在這樣的場景下,默認的批處理 的大小是比較合適的,因爲壓縮超過1000條壓縮記錄時也基本無法獲得更高的壓縮比了。

–conf spark.sql.parquet.compressed.codec
默認值爲snappy 這個參數代表使用哪種壓縮編碼器。可選的選項包括uncompressed/snappy/gzip/lzo uncompressed這個顧名思義就是不用壓縮的意思

–conf spark.speculation
推測執行優化機制採用了典型的以空間換時間的優化策略,它同時啓動多個相同task(備份任務)處理相同的數據塊,哪個完成的早,則採用哪個task的結果,這樣可防止拖後腿Task任務出現,進而提高作業計算速度,但是,這樣卻會佔用更多的資源,在集羣資源緊缺的情況下,設計合理的推測執行機制可在多用少量資源情況下,減少大作業的計算時間。
檢查邏輯代碼中註釋很明白,當成功的Task數超過總Task數的75%(可通過參數spark.speculation.quantile設置)時,再統計所有成功的Tasks的運行時間,得到一箇中位數,用這個中位數乘以1.5(可通過參數spark.speculation.multiplier控制)得到運行時間門限,如果在運行的Tasks的運行時間超過這個門限,則對它啓用推測。簡單來說就是對那些拖慢整體進度的Tasks啓用推測,以加速整個Stage的運行
spark.speculation.interval 100毫秒 Spark經常檢查要推測的任務。
spark.speculation.multiplier 1.5 任務的速度比投機的中位數慢多少倍。
spark.speculation.quantile 0.75 在爲特定階段啓用推測之前必須完成的任務的分數。

–conf spark.shuffle.consolidateFiles
默認值:false
參數說明:如果使用HashShuffleManager,該參數有效。如果設置爲true,那麼就會開啓consolidate機制,會大幅度合併shuffle write的輸出文件,對於shuffle read task數量特別多的情況下,這種方法可以極大地減少磁盤IO開銷,提升性能。
調優建議:如果的確不需要SortShuffleManager的排序機制,那麼除了使用bypass機制,還可以嘗試將spark.shffle.manager參數手動指定爲hash,使用HashShuffleManager,同時開啓consolidate機制。在實踐中嘗試過,發現其性能比開啓了bypass機制的SortShuffleManager要高出10%~30%。

–conf spark.shuffle.file.buffer
默認值:32k
參數說明:該參數用於設置shuffle write task的BufferedOutputStream的buffer緩衝大小。將數據寫到磁盤文件之前,會先寫入buffer緩衝中,待緩衝寫滿之後,纔會溢寫到磁盤。
調優建議:如果作業可用的內存資源較爲充足的話,可以適當增加這個參數的大小(比如64k,一定是成倍的增加),從而減少shuffle write過程中溢寫磁盤文件的次數,也就可以減少磁盤IO次數,進而提升性能。在實踐中發現,合理調節該參數,性能會有1%~5%的提升。

–conf spark.reducer.maxSizeInFlight
默認值:48m
參數說明:該參數用於設置shuffle read task的buffer緩衝大小,而這個buffer緩衝決定了每次能夠拉取多少數據。
調優建議:如果作業可用的內存資源較爲充足的話,可以適當增加這個參數的大小(比如96m),從而減少拉取數據的次數,也就可以減少網絡傳輸的次數,進而提升性能。在實踐中發現,合理調節該參數,性能會有1%~5%的提升。

–conf spark.shuffle.io.maxRetries
默認值:3
參數說明:shuffle read task從shuffle write task所在節點拉取屬於自己的數據時,如果因爲網絡異常導致拉取失敗,是會自動進行重試的。該參數就代表了可以重試的最大次數。如果在指定次數之內拉取還是沒有成功,就可能會導致作業執行失敗。
調優建議:對於那些包含了特別耗時的shuffle操作的作業,建議增加重試最大次數(比如60次),以避免由於JVM的full gc或者網絡不穩定等因素導致的數據拉取失敗。在實踐中發現,對於針對超大數據量(數十億~上百億)的shuffle過程,調節該參數可以大幅度提升穩定性。
shuffle file not find taskScheduler不負責重試task,由DAGScheduler負責重試stage

–conf spark.shuffle.io.retryWait
默認值:5s
參數說明:具體解釋同上,該參數代表了每次重試拉取數據的等待間隔,默認是5s。
調優建議:建議加大間隔時長(比如60s),以增加shuffle操作的穩定性。

–conf spark.shuffle.memoryFraction
默認值:0.2
參數說明:該參數代表了Executor內存中,分配給shuffle read task進行聚合操作的內存比例,默認是20%。
調優建議:在資源參數調優中講解過這個參數。如果內存充足,而且很少使用持久化操作,建議調高這個比例,給shuffle read的聚合操作更多內存,以避免由於內存不足導致聚合過程中頻繁讀寫磁盤。在實踐中發現,合理調節該參數可以將性能提升10%左右。

–conf spark.shuffle.manager
默認值:sort|hash
參數說明:該參數用於設置ShuffleManager的類型。Spark 1.5以後,有三個可選項:hash、sort和tungsten-sort。HashShuffleManager是Spark 1.2以前的默認選項,但是Spark 1.2以及之後的版本默認都是SortShuffleManager了。tungsten-sort與sort類似,但是使用了tungsten計劃中的堆外內存管理機制,內存使用效率更高。
調優建議:由於SortShuffleManager默認會對數據進行排序,因此如果你的業務邏輯中需要該排序機制的話,則使用默認的SortShuffleManager就可以;而如果你的業務邏輯不需要對數據進行排序,那麼建議參考後面的幾個參數調優,通過bypass機制或優化的HashShuffleManager來避免排序操作,同時提供較好的磁盤讀寫性能。這裏要注意的是,tungsten-sort要慎用,因爲之前發現了一些相應的bug。

–conf spark.shuffle.sort.bypassMergeThreshold
默認值:200
參數說明:當ShuffleManager爲SortShuffleManager時,如果shuffle read task的數量小於這個閾值(默認是200),則shuffle write過程中不會進行排序操作,而是直接按照未經優化的HashShuffleManager的方式去寫數據,但是最後會將每個task產生的所有臨時磁盤文件都合併成一個文件,並會創建單獨的索引文件。
調優建議:當你使用SortShuffleManager時,如果的確不需要排序操作,那麼建議將這個參數調大一些,大於shuffle read task的數量。那麼此時就會自動啓用bypass機制,map-side就不會進行排序了,減少了排序的性能開銷。但是這種方式下,依然會產生大量的磁盤文件,因此shuffle write性能有待提高。

–conf spark.shuffle.consolidateFiles
默認值:false
參數說明:如果使用HashShuffleManager,該參數有效。如果設置爲true,那麼就會開啓consolidate機制,會大幅度合併shuffle write的輸出文件,對於shuffle read task數量特別多的情況下,這種方法可以極大地減少磁盤IO開銷,提升性能。
調優建議:如果的確不需要SortShuffleManager的排序機制,那麼除了使用bypass機制,還可以嘗試將spark.shffle.manager參數手動指定爲hash,使用HashShuffleManager,同時開啓consolidate機制。在實踐中嘗試過,發現其性能比開啓了bypass機制的SortShuffleManager要高出10%~30%。

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