Spark 性能相關參數配置詳解-Storage篇

隨着Spark的逐漸成熟完善愈來愈多的可配置參數被添加到Spark中來本文試圖經過闡述這其中部分參數的工做原理和配置思路和你們一塊兒探討一下如何根據實際場合對Spark進行配置優化。算法


因爲篇幅較長,因此在這裏分篇組織,若是要看最新完整的網頁版內容,能夠戳這裏:http://spark-config.readthedocs.org/,主要是便於更新內容數據結構



Storage相關配置參數性能


spark.local.dir優化

 

這個看起來很簡單,就是Spark用於寫中間數據,如RDD CacheShuffleSpill等數據的位置,那麼有什麼能夠注意的呢。spa

 

首先,最基本的固然是咱們能夠配置多個路徑(用逗號分隔)到多個磁盤上增長總體IO帶寬,這個你們都知道。對象

 

其次,目前的實現中,Spark是經過對文件名採用hash算法分佈到多個路徑下的目錄中去,若是你的存儲設備有快有慢,好比SSD+HDD混合使用,那麼你能夠經過在SSD上配置更多的目錄路徑來增大它被Spark使用的比例,從而更好地利用SSDIO帶寬能力。固然這只是一種變通的方法,終極解決方案仍是應該像目前HDFS的實現方向同樣,讓Spark可以感知具體的存儲設備類型,針對性的使用。隊列

 

須要注意的是,在Spark 1.0 之後,SPARK_LOCAL_DIRS(Standalone, Mesos) or LOCAL_DIRS (YARN)參數會覆蓋這個配置。好比Spark On YARN的時候,Spark Executor的本地路徑依賴於Yarn的配置,而不取決於這個參數。內存

 

 

spark.executor.memory資源

 

Executor 內存的大小,和性能自己固然並無直接的關係,可是幾乎全部運行時性能相關的內容都或多或少間接和內存大小相關。這個參數最終會被設置到Executor的JVM的heap尺寸上,對應的就是Xmx和Xms的值文檔

 

理論上Executor 內存固然是多多益善,可是實際受機器配置,以及運行環境,資源共享,JVM GC效率等因素的影響,仍是有可能須要爲它設置一個合理的大小。 多大算合理,要看實際狀況

 

Executor的內存基本上是Executor內部全部任務共享的,而每一個Executor上能夠支持的任務的數量取決於Executor所管理的CPU Core資源的多少,所以你須要瞭解每一個任務的數據規模的大小,從而推算出每一個Executor大體須要多少內存便可知足基本的需求。

 

如何知道每一個任務所需內存的大小呢,這個很難統一的衡量,由於除了數據集自己的開銷,還包括算法所需各類臨時內存空間的使用,而根據具體的代碼算法等不一樣,臨時內存空間的開銷也不一樣。可是數據集自己的大小,對最終所需內存的大小仍是有必定的參考意義的。

 

一般來講每一個分區的數據集在內存中的大小,多是其在磁盤上源數據大小的若干倍(不考慮源數據壓縮,Java對象相對於原始裸數據也還要算上用於管理數據的數據結構的額外開銷),須要準確的知道大小的話,能夠將RDD cache在內存中,從BlockManagerLog輸出能夠看到每一個Cache分區的大小(其實也是估算出來的,並不徹底準確)

 

如: BlockManagerInfo: Added rdd_0_1 on disk on sr438:41134(size: 495.3 MB)

 

 

反過來講,若是你的Executor的數量和內存大小受機器物理配置影響相對固定,那麼你就須要合理規劃每一個分區任務的數據規模,例如採用更多的分區,用增長任務數量(進而須要更多的批次來運算全部的任務)的方式來減少每一個任務所需處理的數據大小。

 

 

spark.storage.memoryFraction

 

如前面所說spark.executor.memory決定了每一個Executor可用內存的大小,而spark.storage.memoryFraction則決定了在這部份內存中有多少能夠用於Memory Store管理RDD Cache數據,剩下的內存用來保證任務運行時各類其它內存空間的須要。

 

spark.executor.memory默認值爲0.6,官方文檔建議這個比值不要超過JVM Old Gen區域的比值。這也很容易理解,由於RDD Cache數據一般都是長期駐留內存的,理論上也就是說最終會被轉移到Old Gen區域(若是該RDD尚未被刪除的話),若是這部分數據容許的尺寸太大,勢必把Old Gen區域佔滿,形成頻繁的FULL GC

 

如何調整這個比值,取決於你的應用對數據的使用模式和數據的規模,粗略的來講,若是頻繁發生Full GC,能夠考慮下降這個比值,這樣RDD Cache可用的內存空間減小(剩下的部分Cache數據就須要經過Disk Store寫到磁盤上了),會帶來必定的性能損失,可是騰出更多的內存空間用於執行任務,減小Full GC發生的次數,反而可能改善程序運行的總體性能

 

 

spark.streaming.blockInterval

 

這個參數用來設置Spark StreamingStream Receiver生成Block的時間間隔,默認爲200ms。具體的行爲表現是具體的Receiver所接收的數據,每隔這裏設定的時間間隔,就從Buffer生成一個StreamBlock放進隊列,等待進一步被存儲到BlockManager中供後續計算過程使用。理論上來講,爲了每一個StreamingBatch 間隔裏的數據是均勻的,這個時間間隔固然應該能被Batch的間隔時間長度所整除。整體來講,若是內存大小夠用,Streaming的數據來得及處理,這個blockInterval時間間隔的影響不大,固然,若是數據Cache LevelMemory+Ser,即作了序列化處理,那麼BlockInterval的大小會影響序列化後數據塊的大小,對於Java GC的行爲會有一些影響。

 

此外spark.streaming.blockQueueSize決定了在StreamBlock被存儲到BlockMananger以前,隊列中最多能夠容納多少個StreamBlock。默認爲10,由於這個隊列Poll的時間間隔是100ms,因此若是CPU不是特別繁忙的話,基本上應該沒有問題。

相關文章
相關標籤/搜索