Spark內(nèi)存管理解析

      網(wǎng)友投稿 930 2022-05-28

      Spark是一個(gè)基于內(nèi)存的分布式計(jì)算引擎,為了更為高效地利用內(nèi)存,并減少OOM等內(nèi)存問題,Spark對(duì)JVM內(nèi)存模型進(jìn)行了進(jìn)一步的管理規(guī)劃,在其之上實(shí)現(xiàn)了自己的內(nèi)存管理模型。本文將基于spark.memory

      (https://github.com/apache/spark/blob/master/core/src/main/scala/org/apache/spark/memory/package.scala)

      包對(duì)Spark內(nèi)存管理機(jī)制進(jìn)行簡(jiǎn)要探索。

      Spark內(nèi)存管理解析

      Spark內(nèi)存管理模型

      與其他JVM進(jìn)程類似,Spark進(jìn)程的內(nèi)存可以分為兩部分,一是由spark.executor.memory指定的JVM堆內(nèi)內(nèi)存,另一部分是由spark.memory.offHeap.size指定的堆外內(nèi)存。這兩部分內(nèi)存邏輯上由MemoryManager

      (https://github.com/apache/spark/blob/master/core/src/main/scala/org/apache/spark/memory/MemoryManager.scala)

      進(jìn)行統(tǒng)一規(guī)劃與分配。MemoryManager的內(nèi)存管理模式是bookkeeping式的,其并不實(shí)際負(fù)責(zé)內(nèi)存的申請(qǐng)與釋放,而是維護(hù)著進(jìn)程中全局內(nèi)存的使用狀況,并根據(jù)一定的策略,對(duì)空閑內(nèi)存進(jìn)行邏輯分配,以及決定是否溢寫(spill)已有數(shù)據(jù)到磁盤等。其中:

      堆內(nèi)內(nèi)存

      MemoryManager將堆內(nèi)內(nèi)存邏輯上劃分為三個(gè)主要內(nèi)存區(qū)域(物理上依然是JVM堆內(nèi)內(nèi)存模型,占用可以任意交叉):

      Reserved?Memory

      這一塊是系統(tǒng)預(yù)留的內(nèi)存,其大小硬編碼為300MB。這意味著這300M內(nèi)存是不計(jì)入Spark內(nèi)存區(qū)域大小的,并且除非重新編譯Spark或者設(shè)置spark.testing.reservedMemory參數(shù),否則這塊內(nèi)存大小是無法更改的。不過官方僅僅只是將spark.testing.reservedMemory配置作為測(cè)試用,并不推薦在生產(chǎn)環(huán)境中更改。記住這塊內(nèi)存僅僅只是被稱作“reserved”,事實(shí)上任何情況下都不能被Spark使用,但是它確定了Spark可以使用的內(nèi)存分配上限。即使你想將所有的Java?Heap給Spark來緩存數(shù)據(jù),reserved部分要保持空閑所以你沒法這樣做(其實(shí)并不是真的空閑,里面會(huì)存儲(chǔ)很多Spark內(nèi)部對(duì)象)。

      User?Memory

      這一部分內(nèi)存區(qū)域是為用戶編寫的Spark應(yīng)用邏輯而預(yù)留的內(nèi)存,其大小為:

      (Java?Heap?-?Reserved?Memory)?*?(1.0?-?spark.memory.fraction)

      該部分內(nèi)存的使用方式完全取決于編寫Spark應(yīng)用的用戶。用戶可以用其存儲(chǔ)轉(zhuǎn)換RDD過程中用到的中間數(shù)據(jù)結(jié)構(gòu)等。比如用戶重寫Spark?aggregation時(shí),可以用其來存儲(chǔ)mapPartition轉(zhuǎn)換過程中用到的hash?table。再次說明一下,這一塊內(nèi)存是User?Memory,存什么和怎么存都取決于開發(fā)者,Spark不會(huì)對(duì)這一部分內(nèi)存區(qū)域作限制及檢查。因而,應(yīng)用代碼中如果忽略了分界,使用了超過該區(qū)域大小的內(nèi)存,可能會(huì)導(dǎo)致OOM(out?of?memory)錯(cuò)誤。

      Spark?Memory

      MemoryManager實(shí)際管理的是Spark?Memory這一部分內(nèi)存區(qū)域,該部分內(nèi)存區(qū)域大小由spark.memory.fraction控制,默認(rèn)為0.6。MemoryManager將該部分區(qū)域進(jìn)一步劃分為兩個(gè)部分:

      - Storage?Memory

      該部分內(nèi)存可用于unroll?RDD,緩存RDD,以及緩存broadcast等的傳輸數(shù)據(jù)。其與Execution?Memory之間的邊界大小由spark.memory.storageFraction控制,默認(rèn)為0.5。

      - Execution?Memory

      該部分內(nèi)存用作shuffle,?joins,?sorts以及aggregations等操作的計(jì)算內(nèi)存。其由所有task共享。不過,對(duì)于各task可使用內(nèi)存,MemoryManager進(jìn)行了進(jìn)一步控制。對(duì)于具有N個(gè)task的進(jìn)程,其確保每個(gè)task在進(jìn)行spill之前,至少能獲得1?/?2N的內(nèi)存,但最多只能獲取1?/?N的內(nèi)存。

      堆外內(nèi)存

      堆外內(nèi)存是Spark在JVM內(nèi)存之外直接開辟的內(nèi)存空間,用于存儲(chǔ)經(jīng)過序列化的二進(jìn)制數(shù)據(jù)。由于該部分內(nèi)存不經(jīng)由JVM內(nèi)存管理模型進(jìn)行申請(qǐng)和釋放,因而MemoryManager可以精確控制這部分內(nèi)存的申請(qǐng)與釋放,以及存儲(chǔ)數(shù)據(jù)需要占用的內(nèi)存空間大小。所以,MemoryManager將該部分內(nèi)存區(qū)域簡(jiǎn)單地劃分為Storage?Memory和Execution?Memory兩部分。

      統(tǒng)一內(nèi)存管理

      對(duì)于Storage?Memory和Execution?Memory的邊界劃分,在Spark?1.6.0之前是由StaticMemoryManager

      (https://github.com/apache/spark/blob/master/core/src/main/scala/org/apache/spark/memory/StaticMemoryManager.scala)

      控制的。其采用的是固定的劃分方式,在這種劃分方式下,即使其中一方有大量空閑內(nèi)存,另一方也無法占用。從而,往往導(dǎo)致在還有大量空閑內(nèi)存的情況下,依然有大量的磁盤溢寫,影響Spark的性能。為了提高內(nèi)存使用率,1.6.0版本的內(nèi)存管理模型引入了軟間隔(soft?boundary)機(jī)制,使得Storage?Memory和Execution?Memory之間得以共享Spark?Memory的空閑內(nèi)存。該內(nèi)存管理模式在UnifiedMemoryManager

      (https://github.com/apache/spark/blob/master/core/src/main/scala/org/apache/spark/memory/UnifiedMemoryManager.scala)

      類中進(jìn)行了實(shí)現(xiàn)。具體地:

      -?spark.storage.storageFraction參數(shù)設(shè)定了Storage?Memory和Execution?Memory的基本區(qū)域,默認(rèn)為0.5。該設(shè)定確定了雙方各自擁有的空間范圍。

      -?雙方的空間都不足時(shí),則溢寫己方內(nèi)存到硬盤;若己方空間不足而對(duì)方空余時(shí),可借用對(duì)方的空間。(存儲(chǔ)空間不足是指不足以放下一個(gè)完整的Block)。

      -?Execution?Memory的空間被對(duì)方占用后,可讓對(duì)方將占用的部分轉(zhuǎn)存到磁盤,然后"歸還"借用的空間。

      -?Storage?Memory的空間被對(duì)方占用后,無法讓對(duì)方"歸還",因?yàn)樾枰紤]執(zhí)行過程中的很多因素,實(shí)現(xiàn)起來較為復(fù)雜。

      總結(jié)

      Spark的統(tǒng)一內(nèi)存管理機(jī)制,在一定程度上提高了內(nèi)存資源的利用率,降低了開發(fā)者維護(hù)及調(diào)優(yōu)內(nèi)存的難度。借助Spark的內(nèi)存管理模型,開發(fā)者可以不再需要過多關(guān)心Spark?Memory這一部分內(nèi)存的內(nèi)存管理。不過,開發(fā)者依然需要注意:

      依據(jù)實(shí)際應(yīng)用場(chǎng)景,確定spark.memory.fraction,并且在應(yīng)用開發(fā)過程中,確保使用的User?Memory不超過(spark.executor.memory?-?300MB)?*?(1.0?-?spark.memory.fraction)。

      對(duì)于需要大量存儲(chǔ)內(nèi)存或者執(zhí)行內(nèi)存的應(yīng)用,可通過spark.memory.offHeap.enabled開啟堆外內(nèi)存,并適當(dāng)配置堆外內(nèi)存大小spark.memory.offHeap.size。

      由于Spark對(duì)堆內(nèi)內(nèi)存的管理受限于JVM垃圾回收機(jī)制的不確定性以及對(duì)非序列化對(duì)象內(nèi)存占用的近似估算,可能導(dǎo)致某一時(shí)刻實(shí)際使用內(nèi)存遠(yuǎn)超預(yù)期,從而其無法完全避免內(nèi)存溢出(OOM)。

      本文只對(duì)Spark邏輯層面的內(nèi)存管理模型進(jìn)行了簡(jiǎn)要介紹,對(duì)于Spark具體存儲(chǔ)過程及執(zhí)行過程中的內(nèi)存操作,可基于MemoryStore

      (https://github.com/apache/spark/blob/master/core/src/main/scala/org/apache/spark/storage/memory/MemoryStore.scala)

      和TaskMemoryManager

      (https://github.com/apache/spark/blob/master/core/src/main/java/org/apache/spark/memory/TaskMemoryManager.java)

      進(jìn)行更為深入的研究。

      參考資源

      Spark?Memory?Management(https://0x0fff.com/spark-memory-management/)

      Apache?Spark?內(nèi)存管理詳解(https://www.ibm.com/developerworks/cn/analytics/library/ba-cn-apache-spark-memory-management/index.html)

      大數(shù)據(jù)

      版權(quán)聲明:本文內(nèi)容由網(wǎng)絡(luò)用戶投稿,版權(quán)歸原作者所有,本站不擁有其著作權(quán),亦不承擔(dān)相應(yīng)法律責(zé)任。如果您發(fā)現(xiàn)本站中有涉嫌抄襲或描述失實(shí)的內(nèi)容,請(qǐng)聯(lián)系我們jiasou666@gmail.com 處理,核實(shí)后本網(wǎng)站將在24小時(shí)內(nèi)刪除侵權(quán)內(nèi)容。

      上一篇:一加40張2K壁紙
      下一篇:Python小白需要做的準(zhǔn)備工作
      相關(guān)文章
      亚洲最新永久在线观看| 亚洲国产另类久久久精品小说| 久久精品国产亚洲| 亚洲精品A在线观看| 美国毛片亚洲社区在线观看| 中文字幕乱码亚洲无线三区| 亚洲国产高清视频在线观看| 亚洲视频在线免费播放| 久久亚洲日韩看片无码| 精品亚洲成a人片在线观看 | 亚洲第一极品精品无码久久| 久99精品视频在线观看婷亚洲片国产一区一级在线 | 亚洲国产精品成人久久| 亚洲精品无码久久久久去q| 亚洲一区二区女搞男| 久久精品国产亚洲网站| 亚洲av无码乱码国产精品| 亚洲AV无一区二区三区久久| 亚洲AV无码国产精品麻豆天美| 亚洲AV无码一区二区乱孑伦AS| 亚洲AV无码久久| 亚洲成人中文字幕| 久久久国产精品亚洲一区| 久久亚洲AV无码精品色午夜麻豆| 久久亚洲精精品中文字幕| 亚洲美女视频一区二区三区| 亚洲精品成人网站在线播放| 亚洲国产成人久久精品app| 亚洲AV无码无限在线观看不卡 | 亚洲熟妇中文字幕五十中出| 亚洲国产精彩中文乱码AV| 亚洲今日精彩视频| 亚洲精品视频在线观看视频| 亚洲免费电影网站| 亚洲性无码AV中文字幕| 亚洲av乱码中文一区二区三区| 人人狠狠综合久久亚洲高清| 亚洲精品无码专区2| 亚洲日韩激情无码一区| 亚洲影院在线观看| 亚洲一区在线视频|