Spark的相關引數配置

业余砖家發表於2024-03-15

一、任務佔用資源計算

executor佔用CPU = executor_instances * executor_cores * 10 * 0.80.1核)

executor佔用記憶體 = executor_instances * (executor.memory + max(executor.memoryOverhead, OffHeap.size) + executor.pyspark.memory)GB

其中,若引數未手動設定,會分配預設值。

也就是說,使用預設引數,每個executor就會分配4g + max(5g, 3.7g) + 6g = 15g的記憶體,對於一般任務已經足夠使用。

-- driver

spark.driver.cores 1

spark.driver.memory 4g

-- executor

spark.executor.cores 2

spark.executor.memory 4g

spark.executor.memoryOverhead 5g

spark.executor.pyspark.memory 6g

-- Bytes,約為3.7G

spark.memory.offHeap.size 4000000000

二、使用者需要關注的引數

如上,在使用預設配置時,每個executor就會分配15g記憶體,已經足夠一般任務使用。

所以使用者一般只需配置spark.executor.instancesspark.sql.shuffle.partitionsspark.default.parallelism即可。

如果配置後發現還是報OOM錯誤,可適當提高記憶體引數,重要引數含義見下方。

推薦配置:

spark.executor.instances 50

spark.sql.shuffle.partitions 300

spark.default.parallelism 300

三、重要引數含義

1driver相關引數

driver實際申請記憶體大小計算公式:driver.memory + driver.memoryOverhead

(1)spark.driver.memory

driver程序(JVM使用)的記憶體數,一般(memory/cores >= 2g

通用配置:4g

df.collect()會返回所有資料的list,但是這個方法會將所有資料pulldriver,所以在遇到driver爆記憶體時,可以注意這一點。引數driver.memory調高。

引數調優建議:Driver的記憶體通常來說不設定,或者設定1G左右應該就夠了。

(2)spark.driver.cores

預設1driver程式使用的CPU核心數,若無過多driver單機處理操作,一般不需要配置

通用配置:2

(3)spark.driver.memoryOverhead

driver JVM堆外記憶體的大小,預設為max(384, 0.1 * spark.driver.memory)

此配置存在預設單位MB,因此直接配置數字或帶具體單位,最少1g

通用配置:1g

2executor相關引數

(1)spark.executor.instances

設定spark作業executor的個數executor.instances * executor.cores為當前application內並行執行task數,需要根據spark.sql.shuffle.partitions判斷,一般保證executor.instances * executor.cores <= partitions / 2

通用配置:10

引數調優建議:每個Spark作業的執行一般設定50~100個左右的Executor程序比較合適,設定太少或太多的Executor程序都不好。設定的太少,無法充分利用叢集資源;設定的太多的話,大部分佇列可能無法給予充分的資源。

(2)spark.executor.memory

每個executor程序(JVM使用)的記憶體大小

預設配置:4g

引數調優建議:每個Executor程序的記憶體設定4G~8G較為合適。但是這只是一個參考值,具體的設定還是得根據不同部門的資源佇列來定。可以看看自己團隊的資源佇列的最大記憶體限制是多少,num-executors乘以executor-memory,是不能超過佇列的最大記憶體量的。此外,如果你是跟團隊裡其他人共享這個資源佇列,那麼申請的記憶體量最好不要超過資源佇列最大總記憶體的1/4~1/3,避免你自己的Spark作業佔用了佇列所有的資源,導致別的同學的作業無法執行

(3)spark.executor.cores

每個executorcore數目。每個core同一時間只能執行一個Task執行緒,cores的數目也就意味著每個executor並行task的數目。

每個task分配的記憶體大小是executor-memory/executor-cores,可以按照這個分析每個task所佔用的記憶體大小,一般(memory/cores >= 2g)。

每個executor1個程序,分配一個JVM,考慮到JVM載入task資訊的數量,cores個數不要超過5,超出後會容易出現大量載入任務資訊導致OOM的情況。

預設配置:2

(4)spark.executor.memoryOverhead

executor JVM堆外記憶體大小,一般執行非JVM的邏輯

此部分記憶體主要用於JVM自身,字串, NIO BufferDriect Buffer)等開銷。此部分為使用者程式碼及Spark 不可操作的記憶體,不足時可透過調整引數解決。

此配置存在預設單位MB,因此直接配置數字或帶具體單位,最少1g

預設配置:5g

(5)spark.executor.pyspark.memory

pythonworker記憶體,僅在使用pyspark時生效

預設配置:6g

(6)spark.shuffle.spill.numElementsForceSpillThreshold

預設256000000,即256M

shuffle超過該資料會強行落盤此配置存在單位B,因此直接配置數字即可

通用配置:256000000

(7)spark.sql.shuffle.partitions

Spark SQL專用的設定

預設200,用於設定shufflepartition的數目,只作用於SQLDataSetjoin/aggregations,無法對純map操作生效。該引數代表了shuffle read task的並行度。

在使用者shuffle OOM時,可考慮增大數目

通用配置:200

(8)spark.default.parallelism

在處理RDD時才會起作用,對Spark SQL的無效

預設200,與上面作用相同,只作用於RDDjoin/reduceByKey等,無法對純map操作生效。

通用配置:200

通常來說,Spark預設設定的數量是偏少的(比如就幾十個task),如果task數量偏少的話,就會導致你前面設定好的Executor的引數都前功盡棄。試想一下,無論你的Executor程序有多少個,記憶體和CPU有多大,但是task只有1個或者10個,那麼90%Executor程序可能根本就沒有task執行,也就是白白浪費了資源!

Spark官網建議的設定原則是,設定該引數為num-executors * executor-cores2~3倍較為合適,比如Executor的總CPU core數量為300個,那麼設定1000task是可以的,此時可以充分地利用Spark叢集的資源。

(9)spark.memory.fraction

預設0.75,用於存放快取資料和執行資料,剩餘0.25User Memory,存放使用者定義的資料結構和Spark後設資料資訊。

在使用者persist大量資料或者shuffle聚合資料量比較大時可以考慮增加該值

快取持久化(persist) + 執行(shuffle+執行編寫的程式碼) = memory.fraction,預設為0.75persistmemory.storageFraction引數指定,預設0.5

(10)spark.memory.storageFractionspark.memory.useLegacyMode(代表啟用spark1.6前的版本)時,spark.storage.memoryFraction

預設0.5storage記憶體大小,用於儲存快取資料,剩餘空間用於execute

Unified Memory Manage模式下,記憶體會自動調整,分配storageexecute使用,但是在storage記憶體不足時,會要回所有分配的記憶體。

在使用者shuffle處理資料比較大時可減小該引數

(11)spark.memory.offHeap.size

設定JVM堆外記憶體大小,可以執行executor JVM相關計算,預設為5000000000,即5G

一般任務中只有部分shuffle需要大量操作,記憶體可能OOM時啟用,在spark.memory.offHeap.enabled設為true時啟用。

此配置存在單位B,因此直接配置數字即可

預設配置:4000000000

相關文章