Spark 1.6以後的內存管理機制

 Spark 內部管理機制

   Spark的內存管理自從1.6開始改變。老的內存管理實現自自staticMemoryManager類,然而現在它被稱之爲”legacy”. “Legacy” 默認已經被廢棄掉了,它意味着相同的代碼在1.5版本與1.6版本的輸出結果將會不同。需要注意的是,出於兼容性的考慮,你依舊可以使用”legacy”,通過設置spark.memory.useLegacyMode改變。 自從spark1.6版本開始,內存管理將實現自UnifiedMemoryManager.那麼新的內存管理如下圖:

        

          

 

1、預留內存。

爲系統預留的內存。同時它是寫死的300MB大小。這300MB的內存大小並不在spark計算與緩存內存之中,同時它在任何情況下都不能被改變,除非重新編譯或者是設置參數spark.testing.reservedMemory

事實上,它並不被spark所用,即便你想將所有的內存設置爲堆內存爲spark緩存數據,你也無法佔用這一部分內存資源。(用來存儲spark的對象信息等)所以如果你不給spark的每個executor至少1.5*Reserved Memory = 415MB,將會報 please use larger heap size的錯誤信息。

2、 計算內存

它是一個爲spark分配的內存池。它取決於你使用它的方式,可將數據結構用於transformations操作,比如,你可以將你的聚合類操作使用mapPartitions轉換爲hash表的形式進行操作。那麼它將消耗spark的使用內存。

在spark1.6.0的內存池中,計算內存的容量爲(“java Heap”-300MB)*(1-spark.memory.fraction),如果按照默認的設置爲(“java-heap”-“Reserved Memory) * 0.25。所以在代碼中,我們需要根據數據量來設定相關的參數,來防止OOM的發生。

3、 存儲內存

Spark的存儲內存被也分爲存儲內存與執行內存。它們的比例可通過spark.memory.storageFraction來設置。默認值爲0.5 。使用這種新的內存管理機制的好處在於,使用邊界不再是靜態的。

Storage Memory 這個資源池被Spark用來緩存數據以及那些沒有進行展開的序列化數據作的臨時空間,所有的boradcast的廣播變量也存儲於該緩存塊中。那些沒有展開的序列化數據將會被返回driver。以及所有的boadcast廣播數據的等級來源於 MEMORY_AND_DISK的設置等級。

Execution Memory 這個資源池按我的理解,用來執行shuffle操作的task。它主要用於shuffle過程中map結果的緩存,是以hash作爲聚合散列的。同時,支持如果沒有足夠的內存時,將map的結果寫入磁盤。所以,不是說shuffle操作就直接將數據寫入磁盤的,也是有個內存緩衝區,我還在想,連hadoop都有緩衝環了,spark還是直接寫磁盤嗎?NONONO。。

 

本文翻譯自一位國外大神的博客:https://0x0fff.com/spark-memory-management/

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章