spark內存管理這一篇就夠了

1. 堆內和堆外內存規劃

1.1 堆內內存

堆內內存的大小,由 Spark 應用程序啟動時的 –executor-memory 或 spark.executor.memory 參數配置。Executor 內運行的並發任務共享 JVM 堆內內存,這些任務在緩存 RDD 數據和廣播(Broadcast)數據時佔用的內存被規劃為存儲(Storage)內存,而這些任務在執行 Shuffle 時佔用的內存被規劃為執行(Execution)內存,剩餘的部分不做特殊規劃,那些 Spark 內部的對象實例,或者用戶定義的 Spark 應用程序中的對象實例,均佔用剩餘的空間。不同的管理模式下,這三部分佔用的空間大小各不相同。

1.2 堆外內存

在默認情況下堆外內存並不啟用,可通過配置 spark.memory.offHeap.enabled 參數啟用,並由 spark.memory.offHeap.size 參數設定堆外空間的大小。除了沒有 other 空間,堆外內存與堆內內存的劃分方式相同,所有運行中的並發任務共享存儲內存和執行內存。

2 . 內存空間分配

2.1 統一內存管理

Spark 1.6 之後引入的統一內存管理機制,與靜態內存管理的區別在於存儲內存和執行內存共享同一塊空間,可以動態佔用對方的空閑區域,如圖 4 和圖 5 所示

圖 4 . 統一內存管理圖示——堆內

spark.memory.fraction       堆內的存儲內存和執行內存總共所佔的比例,默認0.6

spark.storage.storageFraction     用於緩存數據的內存比例,默認0.5

圖 5 . 統一內存管理圖示——堆外

spark.memory.storageFraction         Storage內存所佔堆外內存的比例,默認為0.5

其中最重要的優化在於動態佔用機制,其規則如下:

  • 設定基本的存儲內存和執行內存區域(spark.storage.storageFraction 參數),該設定確定了雙方各自擁有的空間的範圍
  • 雙方的空間都不足時,則存儲到硬盤;若己方空間不足而對方空餘時,可借用對方的空間;(存儲空間不足是指不足以放下一個完整的 Block)
  • 執行內存的空間被對方佔用後,可讓對方將佔用的部分轉存到硬盤,然後”歸還”借用的空間(執行內存的強勢)
  • 存儲內存的空間被對方佔用後,無法讓對方”歸還”,因為需要考慮 Shuffle 過程中的很多因素,實現起來較為複雜

圖 6 . 動態佔用機製圖示

憑藉統一內存管理機制,Spark 在一定程度上提高了堆內和堆外內存資源的利用率,降低了開發者維護 Spark 內存的難度,但並不意味着開發者可以高枕無憂。譬如,所以如果存儲內存的空間太大或者說緩存的數據過多,反而會導致頻繁的全量垃圾回收,降低任務執行時的性能,因為緩存的 RDD 數據通常都是長期駐留內存的 。所以要想充分發揮 Spark 的性能,需要開發者進一步了解存儲內存和執行內存各自的管理方式和實現原理。