Spark 靜態內存管理

做者編輯:杜曉蝶,王瑋,任澤
 

Spark 靜態內存管理詳解

1、 內容簡介

      spark從1.6開始引入了動態內存管理模式,即執行內存和存儲內存之間能夠互相搶佔。spark提供兩種內存分配模式,即:靜態內存管理和動態內存管理。該系列文章分別對這兩種內存管理模式的優缺點以及設計原理進行了分析。該篇文章主要針對spark1.6靜態內存管理進行了分析與說明。動態內存管理以及其餘的調優文章後期會陸續爲你們呈現,請你們關注furion。
此外本文會涉及到不少spark的概念,若是讀者對spark比較陌生,能夠在閱讀本文前先了解一下基本概念,參考地址:http://www.jianshu.com/p/e41b18a7e202 

2、 內存空間分配
 
      在 Spark 最初採用的靜態內存管理機制下,存儲內存、執行內存和其餘內存的大小在 Spark 應用程序運行期間均爲固定的,但用戶能夠應用程序啓動前進行配置,堆內內存的分配以下圖所示:html


1.png


      默認狀況下,spark內存管理採用unified模式,若是要開啓靜態內存管理模式。將Spark.memory.useLegacyMode參數調爲true(默認爲false)。官網相關配置以下:算法


2.png


      當調整該參數之後,從SparkEnv.scala中可知,若是爲true,內存管理調用靜態內存類(StaticMemoryManager)。反之,內存管理採用統一內存管理類(UnifiedMemoryManager)。apache


3.png


3、 Execution內存緩存


  •  可用的Execution內存
 
      用於shuffle聚合內存,取決於joins,sorts,aggregations等過程當中頻繁的IO須要的Buffer臨時數據存儲。
      簡單來講,spark在shuffle write的過程當中,每一個executor會將數據寫到該executor的物理磁盤上,下一個stage的task會去上一個stage拉取其須要處理的數據,而且是邊拉取邊進行處理的(和MapReduce的拉取合併數據基本同樣),這個時候會用一個aggregate的數據結構,好比hashmap邊拉取數據邊進行聚合。這部份內存就被稱作execution內
       從getMaxExecutironMemory方法可知,每一個executor分配給execution的內存爲:Execution Memory = systemMaxMemory * memoryFraction(默認0.2) * safetyFraction(默認0.8), 默認爲 executor 最大可用內存 * 0.16。

 


4.png


      Execution內存在運行時會被分配給運行在JVM上的task。這裏不一樣的是,分配給每一個task的內存並非固定的,而是動態的。spark不是一上來就分配固定大小的內存塊給task,而是容許一個task佔據JVM全部execution內存。
每一個JVM上的task能夠最多申請至多1/N的execution內存(N爲active task的個數,由spark.executor.cores指定)。若是task的申請沒有被批准,它會釋放一部份內存,而且下次申請的時候,它會申請更小的一部份內存。

       注意:爲了防止過多的spilling(evict)數據,只有當一個task分配到的內存達到execution內存1/(2N)的時候纔會spill, 若是目前空閒的內存達不到1/(2N)的時候, 內存申請會被阻塞直到其餘的task spill掉它們的內存。若是不這樣限制,假設當前有一個任務佔據了絕大部份內存,那麼新來的task會一直往硬盤spill數據,這樣就會致使比較嚴重的I/O問題。
舉個例子, 某executor先啓動一個task A,並在task B啓動前快速佔用了全部可用內存。(B啓動後)N變成2,task B會阻塞直到task A spill,本身可得到1/(2N)=1/4的execution內存。而一旦task B獲取到了1/4的內存,A和B就都有可能spill了。數據結構


  •  預留內存
 
      Spark之因此有一個SafetyFraction這樣的參數,是爲了不潛在的OOM。例如,進行計算時,有一個提早未預料到的比較大的數據,會致使計算時間延長甚至OOM, safetyFraction爲storage和execution 都提供了額外的buffer以防止此類的數據傾斜。這部份內存叫作預留內存。

4、Storage內存

 


  • 可用的Storage內存
 
       該部份內存用做對RDD的緩存(如調用cache,persist等方法),節點間傳輸的廣播變量。
從StaticMemoryManager的單例對象中可知,最後爲每一個executor分配到的關於storage的內存:StorageMemory=systemMaxMemory*storageMemoryFraction(默認0.6)*safetyFraction(默認爲0.9)=0.54, 也就是說 默認分配executor 最大可用內存的 * 0.54。源碼以下:

 


5.png


  • 預留內存
 
      同Execution內存中的預留部分

 


  • Unroll
 
      unroll是storage中比較特殊的一部分,它默認佔據總內存的20%。
      BlockManager是spark本身實現的內部分佈式文件系統,BlockManager接受數據(可能從本地或者其餘結點)的時候是以iterator的形式,而且這些數據有序列化和非序列化的。須要注如下兩點:
       a) iterator在物理內存上是不連續的,若是後續spark要把數據裝載進內存的話,就須要把這些數據放進一個array(物理上連續)。
       b) 另外,序列化數據須要進行展開,若是直接展開序列化的數據,會形成OOM, 因此,BlockManager會逐漸的展開這個iterator,並逐漸檢查內存裏是否還有足夠的空間用來展開數據放進array裏。

 


6.png


        unroll的優先級仍是比較高的,它使用的內存空間能夠從storage中借用,若是在storage中沒有現存的數據block,它甚至能夠佔據整個storage空間。若是storage中有數據block,它能夠最大drop掉內存的數據是以spark.storage.unrollFraction來控制的。由圖6可知,這部分默認爲storage的20%。
       注意:這個20%的空間並非靜態保留的,而是經過drop掉內存中的數據block來分配的。若是unroll失敗了,spark會把這部分數據evict 到硬盤。

4、 Other部分
 
      這片內存用於程序自己運行所需的內存,以及用戶定義的數據結構和建立的對象,此內存有上面兩部分決定,默認爲0.2。

5、 侷限性

      spark的設計文檔中指出靜態內存有如下侷限性: 
      (1) 沒有適用於全部應用的默認配置,一般須要開發人員針對不一樣的應用進行不一樣的參數配置。好比根據任務的執行邏輯,調整shuffle和storage內存佔比來適應任務的需求。
      (2) 這樣須要開發人員具有較高的spark原理知識。
      (3) 那些不cache數據的應用在運行時只佔用一小部分可用內存,由於默認的內存配置中,storage用去了safety內存的60%。

6、概念補充

      eviction策略:在spark技術文檔中,eviction一詞常常出現。eviction並非單純字面上驅逐的意思。說句題外話,spark咱們一般都把它叫作內存計算框架,嚴格意義來講,spark並非內存計算的新技術。不管是cache仍是persist這類算子,spark在內存安排上,絕大多數用的都是LRU策略(LRU能夠說是一種算法,也能夠算是一種原則,用來判斷如何從Cache中清除對象,而LRU就是「近期最少使用」原則,當Cache溢出時,最近最少使用的對象將被從Cache中清除)。即當內存不夠的時候,會evict掉最遠使用過的內存數據block。當evict的時候,spark會將該數據塊evict到硬盤,而不是單純的拋棄掉。
不管是storage仍是execution的內存空間,當內存區域的空間不夠用的時候,spark都會evict數據到硬盤。
所以,若是開發人員在內存分配上沒有合理的進行分配,不管是在storage仍是execution超過內存的限制的時候,spark會把內存的數據寫到硬盤。若是是storage的狀況,甚至可能把內存的數據所有寫到硬盤並釋放掉內存中的緩存數據。這樣作,無疑會增長系統調用、I/O以及重複計算的開銷。有過開發spark任務中包含大量shuffle stage的同窗應該有同感,shuffle memory不夠的時候,spill到硬盤的數據會很大,致使任務很慢,甚至會致使任務的各類重試最後任務fail掉。這種狀況建議提升shuffle memory fraction。若是是資源調度在yarn上,建議經過spark.yarn.executor.memoryOverhead提升堆外內存,有的時候甚至會調到2g,3g,4g直到任務成功。

7、參考

       【1】 Unified Memory Management in Spark 1.6 ,Andrew Or and Josh Rosen
       【2】https://www.ibm.com/developerw ... erral
      【3】 http://spark.apache.org
      【4】 http://www.jianshu.com/p/e41b18a7e202app

相關文章
相關標籤/搜索