spark 性能調優

轉自: https://www.cnblogs.com/jcchoiling/p/6440709.html

 

核心調優參數如下:

1

2

3

4

5

6

7

num-executors

executor-memory

executor-cores

driver-memory

spark.default.parallelizm

spark.storage.memoryFraction

spark.shuffle.memoryFraction

  • num-executors:該參數一定會被設置,Yarn 會按照 Driver 的申請去最終爲當前的 Application 生產指定個數的 Executors,實際生產環境下應該分配80個左右 Executors 會比較合適呢。
  • executor-memory:這個定義了每個 Executor 的內存,它與 JVM OOM 緊密相關,很多時候甚至決定了 Spark 運行的性能。實際生產環境下建義是 8G 左右,很多時候 Spark 運行在 Yarn 上,內存佔用量不要超過 Yarn 的內存資源的 50%。
  • executor-cores:決定了在 Executors 中能夠並行執行的 Tasks 的個數。實際生產環境下應該分配4個左右,一般情況下不要超過 Yarn 隊列中 Cores 總數量的 50%。
  • driver-memory:默應是 1G
  • spark.default.parallelizm:並行度問題,如果不設置這個參數,Spark 會跟據 HDFS 中 Block 的個數去設置這一個數量,原理是默應每個 Block 會對應一個 Task,默應情況下,如果數據量不是太多就不可以充份利用 executor 設置的資源,就會浪費了資源。建義設置爲 100個,最好 700個左右。Spark官方的建義是每一個 Core 負責 2-3 個 Task。 
  • spark.storage.memoryFraction:默應占用 60%,如果計算比較依賴於歷史數據則可以調高該參數,當如果計算比較依賴 Shuffle 的話則需要降低該比例。
  • spark.shuffle.memoryFraction:默應占用 20%,如果計算比較依賴 Shuffle 的話則需要調高該比例。

 

Spark 更高性能的算子

Shuffle 分開兩部份,一個是 Mapper 端的Shuffle,另外一個就是 Reducer端的 Shuffle,性能調優有一個很重要的總結就是儘量不使用 Shuffle 類的算子,我們能避免就儘量避免,因爲一般進行 Shuffle 的時候,它會把集羣中多個節點上的同一個 Key 匯聚在同一個節點上,例如 reduceByKey。然後會優先把結果數據放在內存中,但如果內存不夠的話會放到磁盤上。Shuffle 在進行數據抓取之前,爲了整個集羣的穩定性,它的 Mapper 端會把數據寫到本地文件系統。這可能會導致大量磁盤文件的操作。如何避免Shuffle可以考慮以下:

  1. 採用 Map 端的 Join (RDD1 + RDD2 )先把一個 RDD1的數據收集過來,然後再通過 sc.broadcast( ) 把數據廣播到 Executor 上;
  2. 如果無法避免Shuffle,退而求其次就是需要更多的機器參與 Shuffle 的過程,這個時候就需要充份地利用 Mapper 端和 Reducer 端機制的計算資源,儘量使用 Mapper 端的 Aggregrate 功能,e.g. aggregrateByKey 操作。相對於 groupByKey而言,更傾向於使用reduceByKey( ) 和 aggregrateByKey( ) 來取代 groupByKey,因爲 groupByKey 不會進行 Mapper 端的操作,aggregrateByKey 可以給予更多的控制。
  3. 如果一批一批地處理數據來說,可以使用 mapPartitions( ),但這個算子有可能會出現 OOM 機會,它會進行 JVM 的 GC 操作!
  4. 如果進行批量插入數據到數據庫的話,建義採用foreachPartition( ) 。
  5. 因爲我們不希望有太多的數據碎片,所以能批量處理就儘量批量處理,你可以調用 coalesce( ) ,把一個更多的並行度的分片變得更少,假設有一萬個數據分片,想把它變得一百個,就可以使用 coalesce( )方法,一般在 filter( ) 算子之後就會用 coalesce( ),這樣可以節省資源。
  6. 官方建義使用 repartitionAndSortWithPartitions( )
  7. 數據進行復用時一般都會進行持久化 persisit( )
  8. 建義使用 mapPartitionWithIndex( )
  9. 也建義使用 tree 開頭的算子,比如說 treeReduce( ) 和 treeAggregrate( )

 

總結

大數據必然要思考的核心性能問題不外乎 CPU 計算、內存管理、磁盤和網絡IO操作,這是無可避免的,但是可以基於這個基礎上進行優化,思考如何最優化的使用計算資源,思考如何在優化代碼,在代碼層面上防避墜入性能弱點;思考如何減少網絡傳輸和思考如何最大程度的實現數據分佈均衡。

在資源管理調優方面可以設置一些參數,比如num-executors、executor-memory、executor-cores、driver-memory、spark.default.parallelizm、spark.storage.memoryFraction、spark.shuffle.memoryFraction

Shuffle 所導致的問題是所有分佈式系統都無法避免的,但是如何把 Shuffle 所帶來的性能問題減少最低,是一個很可靠的優化方向。Shuffle 的第一階段即Mapper端在默應情況下會寫到本地,而reducer通過網絡抓取的同一個 Key 在不同節點上都把它抓取過來,內存可能不夠,不夠的話就寫到磁盤中,這可能會導致大量磁盤文件的操作。在實際編程的時候,可以用一些比較高效的RDD算子,例如 reduceByKey、aggregrateByKey、coalesce、foreachPartition、repartitionAndSortWithPartitions。

 

 

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