性能調優的本質、Spark資源使用原理和調優要點分析

本課主題

  • 大數據性能調優的本質
  • Spark 性能調優要點分析
  • Spark 資源使用原理流程
  • Spark 資源調優最佳實戰
  • Spark 更高性能的算子

 

引言

咱們談大數據性能調優,到底在談什麼,它的本質是什麼,以及 Spark 在性能調優部份的要點,這兩點讓在進入性能調優以前都是一個相當重要的問題,它的本質限制了咱們調優到底要達到一個什麼樣的目標或者說咱們是從什麼本源上進行調優。但願這篇文章能爲讀者帶出如下的啓發:算法

  • 瞭解大數據性能調優的本質
  • 瞭解 Spark 性能調優要點分析
  • 瞭解 Spark 在資源優化上的一些參數調優
  • 瞭解 Spark 的一些比較高效的 RDD 操做算子 

 

大數據性能調優的本質

編程的時候發現一個驚人的規律,軟件是不存在的!全部編程高手級別的人不管作什麼類型的編程,最終思考的都是硬件方面的問題!最終思考都是在一秒、一毫秒、甚至一納秒究竟是如何運行的,而且基於此進行算法實現和性能調優,最後都是回到了硬件!數據庫

在大數據性能的調優,它的本質是硬件的調優!即基於 CPU(計算)、Memory(存儲)、IO-Disk/ Network(數據交互) 基礎上構建算法和性能調優!咱們在計算的時候,數據確定是存儲在內存中的。磁盤IO怎麼去處理和網絡IO怎麼去優化。編程

 

Spark 性能調優要點分析

在大數據性能本質的思路上,咱們應該須要在那些方面進行調優呢?好比:bash

  • 並行度
  • 壓縮
  • 序例化
  • 數據傾斜
  • JVM調優 (例如 JVM 數據結構化優化)
  • 內存調優
  • Task性能調優 (例如包含 Mapper 和 Reducer 兩種類型的 Task)
  • Shuffle 網絡調優 (例如小文件合併)
  • RDD 算子調優 (例如 RDD 複用、自定義 RDD)
  • 數據本地性
  • 容錯調優
  • 參數調優

大數據最怕的就是數據本地性(內存中)和數據傾斜或者叫數據分佈不均衡、數據轉輸,這個是全部分佈式系統的問題!數據傾斜實際上是跟你的業務緊密相關的。因此調優 Spark 的重點必定是在數據本地性和數據傾斜入手。網絡

  • 資源分配和使用:你可以申請多少資源以及如何最優化的使用計算資源
  • 關發調優:如何基於 Spark 框架內核原理和運行機制最優化的實現代碼功能
  • Shuffle調優:分佈式系統必然面臨的殺手級別的問題
  • 數據傾斜:分佈式系統業務自己有數據傾斜

 

Spark 資源使用原理流程

這是一張來至於官方的經典資源使用流程圖,這裏有三大組件,第一部份是 Driver 部份,第二就是具體處理數據的部份,第三就是資源管理部份。這一張圖中間有一個過程,這表示在程序運行以前向資源管理器申請資源。在實際生產環境中,Cluster Manager 通常都是 Yarn 的 ResourceManager,Driver 會向 ResourceManager 申請計算資源(通常狀況下都是在發生計算以前一次性進行申請請求),分配的計算資源就是 CPU Core 和 Memory,咱們具體的 Job 裏的 Task 就是基於這些分配的內存和 Cores 構建的線程池來運行 Tasks 的。數據結構

[下圖是 Spark 官方網站上的經典Spark架框圖]app

固然在 Task 運行的過程當中會大量的消耗內存,而Task又分爲 Mapper 和 Reducer 兩種不一樣類型的 Task,也就是 ShuffleMapTask 和 ResultTask 兩種類型,這類有一個很關建的調優勢就是如何對內存進行使用。在一個 Task 運行的時候,默應會佔用 Executor 總內存的 20%,Shuffle 拉取數據和進行聚合操做等佔用了 20% 的內存,剩下的大概有 60% 是用於 RDD 持久化 (例如 cache 數據到內存),Task 在運行時候是跑在 Core 上的,比較理想的是有足夠的 Core 同時數據分佈比較均勻,這個時候每每可以充分利用集羣的資源。 框架

核心調優參數以下:分佈式

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。

相關文章
相關標籤/搜索