以該命令為例,我們設定一個executor並分配記憶體為2800m,可以看到ui上只給executor分配了1.5G的記憶體。同理,如果你設定了--executor-memory=1g
,那麼實際上只會有1048.8M的記憶體會被分配。
spark-submit --master yarn \
--num-executors=1 \
--executor-memory=2800m \
--class org.apache.spark.examples.SparkPi \
/opt/module/spark-3.5.1-bin-hadoop3/examples/jars/spark-examples_2.12-3.5.1.jar 1000
這個問題是因為顯示的記憶體為,(heap space - 300MB) * spark.memory.fraction
所劃分的記憶體。詳細介紹參見文件 https://spark.apache.org/docs/latest/tuning.html#memory-management-overview
記憶體管理概覽
在 Spark 中,記憶體使用主要分為兩大類:執行記憶體和儲存記憶體。執行記憶體用於計算處理,如 shuffles(洗牌)、joins(連線)、sorts(排序)和 aggregations(聚合);而儲存記憶體則用於快取和在叢集中傳播內部資料。在 Spark 中,執行記憶體和儲存記憶體共享一個統一的區域(M)。當沒有使用執行記憶體時,儲存記憶體可以佔用所有可用的記憶體,反之亦然。在必要時,執行記憶體可以驅逐儲存記憶體,但只到儲存記憶體的使用量降到某個閾值(R)以下。換句話說,R 描述了 M 中的一個子區域,在該區域內,快取的資料塊不會被驅逐。由於實現機制的複雜性,儲存記憶體不能驅逐執行記憶體。
此設計確保了幾項理想的特性。首先,不利用快取的應用可以使用全部記憶體空間進行執行操作,避免不必要的磁碟溢位。其次,利用快取的應用可以預留一定的儲存空間(R),確保其資料塊不會被驅逐。最後,這種方法為多種工作負載提供了合理的即插即用效能,而無需使用者深入瞭解內部記憶體劃分的細節。
儘管有兩個相關的配置引數,但典型使用者通常不需要調整它們,因為預設值已適用於大多數工作負載:
spark.memory.fraction
表示 M 佔用的比例,計算公式為 (JVM 堆空間 - 300MiB) 的百分比(預設值為 0.6)。其餘的空間(40%)留給使用者資料結構、Spark 的內部後設資料以及作為安全儲備,以防出現稀疏或異常大的記錄導致的 OOM(記憶體溢位)錯誤。spark.memory.storageFraction
表示 R 佔 M 的比例(預設值為 0.5)。R 是 M 內部的一塊儲存區域,其內的快取資料塊不會被執行操作驅逐。
spark.memory.fraction
的值應該設定在能夠在 JVM 的老年代或“終身代”中舒適適應這部分堆空間。