1. 程式人生 > >[Spark進階]-- 記憶體管理

[Spark進階]-- 記憶體管理

前言

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 記憶體的難度,但並不意味著開發者可以高枕無憂。譬如,所以如果儲存記憶體的 空間太大

或者說 快取的資料 過多,反而會導致頻繁的全量垃圾回收,降低任務執行時的效能,因為快取的 RDD 資料通常都是長期駐留記憶體的。所以要想充分發揮 Spark 的效能,需要開發者進一步瞭解儲存記憶體和執行記憶體各自的管理方式和實現原理。

統一記憶體管理還可以簡化如圖
在這裡插入圖片描述
(1)Reserved Memory

  • 不推薦改變此引數(預設即可);
  • 系統保留的記憶體,從Spark 1.6.0開始,它的值為300MB,如果沒有Spark重新編譯或設定 spark.testing.reservedMemory,它的大小不能以任何方式改變,,因為它不是用於生產的測試引數。
  • 如果沒有給Spark執行程式至少 1.5 保留記憶體 = 450MB heap,spark-submit 將失敗並顯示
    **“please use larger heap size”*** 的錯誤訊息。

(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、以上內容是整合參考中的文章後,結合自己的理解而編寫,難免有敘述不周之處,如有發現,多多包涵、還請賜教。

參考