[Spark進階]-- 記憶體管理
阿新 • • 發佈:2018-11-28
前言
Spark 的記憶體管理是記憶體分散式引擎中的一個重要角色,瞭解記憶體管理機制和原理,才能更好地做優化。
內容
1、靜態記憶體管理(Spark 1.6.x版本前的策略)
靜態記憶體管理圖示——堆內
Unroll 的原始碼參考:https://github.com/apache/spark/blob/branch-1.6/core/src/main/scala/org/apache/spark/storage/MemoryStore.scala#L249
靜態記憶體管理圖示——堆外
2、統一記憶體管理(Spark 1.6.x以後的策略)
統一記憶體管理圖示——堆內
統一記憶體管理圖示——堆外
其中最重要的優化在於動態佔用機制,其規則如下:
1\設定基本的儲存記憶體和執行記憶體區域(spark.storage.storageFraction 引數),該設定確定了雙方各自擁有的空間的範圍
雙方的空間都不足時,則儲存到硬碟;若己方空間不足而對方空餘時,可借用對方的空間;(儲存空間不足是指不足以放下一個完整的 Block)
2\執行記憶體的空間被對方佔用後,可讓對方將佔用的部分轉存到硬碟,然後"歸還"借用的空間
3\儲存記憶體的空間被對方佔用後,無法讓對方"歸還",因為需要考慮 Shuffle 過程中的很多因素,實現起來較為複雜
動態佔用機制圖示
憑藉統一記憶體管理機制,Spark 在一定程度上提高了堆內和堆外記憶體資源的利用率,降低了開發者維護 Spark 記憶體的難度,但並不意味著開發者可以高枕無憂。譬如,所以如果儲存記憶體的 空間太大
統一記憶體管理還可以簡化如圖
(1)Reserved Memory
- 不推薦改變此引數(預設即可);
- 系統保留的記憶體,從Spark 1.6.0開始,它的值為300MB,如果沒有Spark重新編譯或設定 spark.testing.reservedMemory,它的大小不能以任何方式改變,,因為它不是用於生產的測試引數。
- 如果沒有給Spark執行程式至少 1.5 保留記憶體 = 450MB heap,spark-submit 將失敗並顯示
(2)User Memory
- 在分配 Spark Memory之後剩餘的記憶體池;
- 使用者可以在那裡儲存將在RDD轉換中使用的資料結構、Spark的元資料,所以必須在編碼中注意資料結構的定義和使用;
- 記憶體池的大小可以計算為(“ Java heap ” - “reserved memory ”)(1.0 - spark.memory.fraction),預設情況下等於(“ Java堆 ” - 300MB ) 0.25
(3)Spark Memory
- Apache Spark管理的記憶體池;
- 計算:(“ Java堆 ” - “保留記憶體 ”)* spark.memory.fraction,並且使用Spark 1.6.0預設值它給我們(“ Java堆 ” - 300MB)* 0.75。
Execution Memory 和 Storage Memory 的邊界由 spark.memory.storageFraction 設定 引數,預設為0.5。 - Storage Memory:這個記憶體用於快取以後還會用到的資料:如廣播變數 、persist
- Execution Memory:這個記憶體用於儲存執行Spark shuffles、joins、sorts和aggregations 期間所需的物件。
3、靜態記憶體管理和統一記憶體管理的區別
靜態記憶體管理 | 統一記憶體管理 | |
---|---|---|
不同點 | 每個區域都有預留記憶體,通過引數控制佔比 | 只有一個預留記憶體區域,且該區域是單獨的 |
相同點 | 分為三個區域(Storage、Execution和 Other)+ 保留記憶體 | 分為3個區域(Spark Memory(包含 Storage 和 Execution)、User Memory(Other))+保留記憶體 |
4、Spark 大部分版本的記憶體引數整理
選項 | spark 1.6.x之前版本 | spark 1.6.x | spark 2.1.x | spark 2.2.x | spark 2.3.x | spark 2.4.x | 備註 |
---|---|---|---|---|---|---|---|
spark.memory.fraction | 無值 | 0.75 | 0.6 | 0.6 | 0.6 | 0.6 | |
spark.memory.storageFraction | 無值 | 0.5 | 0.5 | 0.5 | 0.5 | 0.5 | |
spark.memory.offHeap.enabled | 無值 | false | false | false | false | false | |
spark.memory.offHeap.size | 無值 | 0 | 0 | 0 | 0 | 0 | |
spark.memory.useLegacyMode | 無值 | false | false | false | false | false | |
spark.shuffle.memoryFraction | 0.2 | 0.2 | 0.2 | 0.2 | 0.2 | 0.2 | |
spark.storage.memoryFraction | 0.6 | 0.6 | 0.6 | 0.6 | 0.6 | 0.6 | |
spark.storage.unrollFraction | 0.2 | 0.2 | 0.6 | 0.2 | 0.2 | 0.2 | |
spark.storage.replication.proactive | 無值 | 無值 | 無值 | false | false | false | |
spark.cleaner.periodicGC.interval | 無值 | 無值 | 無值 | 無值 | 30min | 30min | |
spark.cleaner.referenceTracking | 無值 | 無值 | 無值 | 無值 | true | true | |
spark.cleaner.referenceTracking.blocking | 無值 | 無值 | 無值 | 無值 | true | true | |
spark.cleaner.referenceTracking.blocking.shuffle | 無值 | 無值 | 無值 | 無值 | false | false | |
spark.cleaner.referenceTracking.cleanCheckpoints | 無值 | 無值 | 無值 | 無值 | false | false |
說明
-
1、Spark 記憶體:本文中均指 Executor 記憶體
-
2、本文中的分析是基於 Spark v1.6.x 版本
-
3、以上內容是整合參考中的文章後,結合自己的理解而編寫,難免有敘述不周之處,如有發現,多多包涵、還請賜教。
參考
- https://spark.apache.org/docs/1.6.3/configuration.html#memory-management
- https://www.ibm.com/developerworks/cn/analytics/library/ba-cn-apache-spark-memory-management/index.html
- https://0x0fff.com/spark-memory-management/
- https://databricks.com/session/deep-dive-apache-spark-memory-management
- https://blog.csdn.net/u012102306/article/details/51637366
- http://www.importnew.com/26541.html