1基本概念和原則
每一臺host上面可以并行N個worker,每一個worker下面可以并行M個executor,task們會被分配到executor上面去執行,Stage指的是一組并行運行的task,stage內部是不能出現shuffle的,因為shuffle的就像籬笆一樣阻止了并行task的運行,遇到shuffle就意味著到了stage的邊界,
CPU的core數量,每個executor可以占用一個或多個core,可以通過觀察CPU的使用率變化來了解計算資源的使用情況,例如,很常見的一種浪費是一個executor占用了多個core,但是總的CPU使用率卻不高(因為一個executor并不總能充分利用多核的能力),這個時候可以考慮讓一個executor占用更少的core,同時worker下面增加更多的executor,或者一臺host上面增加更多的worker來增加并行執行的executor的數量,從而增加CPU利用率,但是增加executor的時候需要考慮好記憶體消耗,因為一臺機器的記憶體分配給越多的executor,每個executor的記憶體就越小,以致出現過多的資料spill over甚至out of memory的情況,
partition和parallelism,partition指的就是資料分片的數量,每一次task只能處理一個partition的資料,這個值太小了會導致每片資料量太大,導致記憶體壓力,或者諸多executor的計算能力無法利用充分;但是如果太大了則會導致分片太多,執行效率降低,在執行action型別操作的時候(比如各種reduce操作),partition的數量會選擇parent RDD中最大的那一個,而parallelism則指的是在RDD進行reduce類操作的時候,默認回傳資料的paritition數量(而在進行map類操作的時候,partition數量通常取自parent RDD中較大的一個,而且也不會涉及shuffle,因此這個parallelism的引數沒有影響),所以說,這兩個概念密切相關,都是涉及到資料分片的,作用方式其實是統一的,通過spark.default.parallelism可以設定默認的分片數量,而很多RDD的操作都可以指定一個partition引數來顯式控制具體的分片數量,
看這樣幾個例子:
(1)實踐中跑的Spark job,有的特別慢,查看CPU利用率很低,可以嘗試減少每個executor占用CPU core的數量,增加并行的executor數量,同時配合增加分片,整體上增加了CPU的利用率,加快資料處理速度,
(2)發現某job很容易發生記憶體溢位,我們就增大分片數量,從而減少了每片資料的規模,同時還減少并行的executor數量,這樣相同的記憶體資源分配給數量更少的executor,相當于增加了每個task的記憶體分配,這樣運行速度可能慢了些,但是總比OOM強,
(3)資料量特別少,有大量的小檔案生成,就減少檔案分片,沒必要創建那么多task,這種情況,如果只是最原始的input比較小,一般都能被注意到;但是,如果是在運算程序中,比如應用某個reduceBy或者某個filter以后,資料大量減少,這種低效情況就很少被留意到,
最后再補充一點,隨著引數和配置的變化,性能的瓶頸是變化的,在分析問題的時候不要忘記,例如在每臺機器上部署的executor數量增加的時候,性能一開始是增加的,同時也觀察到CPU的平均使用率在增加;但是隨著單臺機器上的executor越來越多,性能下降了,因為隨著executor的數量增加,被分配到每個executor的記憶體數量減小,在記憶體里直接操作的越來越少,spill over到磁盤上的資料越來越多,自然性能就變差了,
下面給這樣一個直觀的例子,當前總的cpu利用率并不高
其次,涉及性能調優我們經常要改配置,在Spark里面有三種常見的配置方式,雖然有些引數的配置是可以互相替代,但是作為最佳實踐,還是需要遵循不同的情形下使用不同的配置:
1.設定環境變數,這種方式主要用于和環境、硬體相關的配置;
2.命令列引數,這種方式主要用于不同次的運行會發生變化的引數,用雙橫線開頭;
3.代碼里面(比如Scala)顯式設定(SparkConf物件),這種配置通常是application級別的配置,一般不改變,
舉一個配置的具體例子,slave、worker和executor之間的比例調整,我們經常需要調整并行的executor的數量,那么簡單說有兩種方式:
1.每個worker內始終跑一個executor,但是調整單臺slave上并行的worker的數量,比如,SPARK_WORKER_INSTANCES可以設定每個slave的worker的數量,但是在改變這個引數的時候,比如改成2,一定要相應設定SPARK_WORKER_CORES的值,讓每個worker使用原有一半的core,這樣才能讓兩個worker一同作業;
2.每臺slave內始終只部署一個worker,但是worker內部署多個executor,我們是在YARN框架下采用這個調整來實作executor數量改變的,一種典型辦法是,一個host只跑一個worker,然后配置spark.executor.cores為host上CPU core的N分之一,同時也設定spark.executor.memory為host上分配給Spark計算記憶體的N分之一,這樣這個host上就能夠啟動N個executor,
有的配置在不同的MR框架/工具下是不一樣的,比如YARN下有的引數的默認取值就不同,這點需要注意,
明確這些基礎的事情以后,再來一項一項看性能調優的要點.
轉載請註明出處,本文鏈接:https://www.uj5u.com/shujuku/224911.html
標籤:其他
上一篇:Spark性能優化指南-美團
下一篇:Spark-2-性能監控方式
