自拍偷在线精品自拍偷,亚洲欧美中文日韩v在线观看不卡

Spark 靜態(tài)內(nèi)存管理詳解

存儲(chǔ) 存儲(chǔ)軟件 Spark
spark從1.6開始引入了動(dòng)態(tài)內(nèi)存管理模式,即執(zhí)行內(nèi)存和存儲(chǔ)內(nèi)存之間可以互相搶占。sspark提供兩種內(nèi)存分配模式:靜態(tài)內(nèi)存管理和動(dòng)態(tài)內(nèi)存管理。

 [[266786]]

一 內(nèi)容簡介

spark從1.6開始引入了動(dòng)態(tài)內(nèi)存管理模式,即執(zhí)行內(nèi)存和存儲(chǔ)內(nèi)存之間可以互相搶占。spark提供兩種內(nèi)存分配模式:靜態(tài)內(nèi)存管理和動(dòng)態(tài)內(nèi)存管理。本系列文章分別對這兩種內(nèi)存管理模式的優(yōu)缺點(diǎn)以及設(shè)計(jì)原理進(jìn)行了分析。主要針對spark1.6靜態(tài)內(nèi)存管理進(jìn)行了分析與說明。

二 內(nèi)存空間分配

在 Spark 最初采用的靜態(tài)內(nèi)存管理機(jī)制下,存儲(chǔ)內(nèi)存、執(zhí)行內(nèi)存和其他內(nèi)存的大小在 Spark 應(yīng)用程序運(yùn)行期間均為固定的,但用戶可以應(yīng)用程序啟動(dòng)前進(jìn)行配置,堆內(nèi)內(nèi)存的分配如下圖所示:

技術(shù)專欄|Spark 靜態(tài)內(nèi)存管理詳解

默認(rèn)情況下,spark內(nèi)存管理采用unified模式,如果要開啟靜態(tài)內(nèi)存管理模式。將Spark.memory.useLegacyMode參數(shù)調(diào)為true(默認(rèn)為false)。官網(wǎng)相關(guān)配置如下:

技術(shù)專欄|Spark 靜態(tài)內(nèi)存管理詳解

當(dāng)調(diào)整該參數(shù)以后,從SparkEnv.scala中可知,如果為true,內(nèi)存管理調(diào)用靜態(tài)內(nèi)存類(StaticMemoryManager)。反之,內(nèi)存管理采用統(tǒng)一內(nèi)存管理類(UnifiedMemoryManager)。

技術(shù)專欄|Spark 靜態(tài)內(nèi)存管理詳解

三 Execution 內(nèi)存

可用的Execution內(nèi)存

用于shuffle聚合內(nèi)存,取決于joins,sorts,aggregations等過程中頻繁的IO需要的Buffer臨時(shí)數(shù)據(jù)存儲(chǔ)。

簡單來說,spark在shuffle write的過程中,每個(gè)executor會(huì)將數(shù)據(jù)寫到該executor的物理磁盤上,下一個(gè)stage的task會(huì)去上一個(gè)stage拉取其需要處理的數(shù)據(jù),并且是邊拉取邊進(jìn)行處理的(和MapReduce的拉取合并數(shù)據(jù)基本一樣),這個(gè)時(shí)候會(huì)用一個(gè)aggregate的數(shù)據(jù)結(jié)構(gòu),比如hashmap邊拉取數(shù)據(jù)邊進(jìn)行聚合。這部分內(nèi)存就被稱做execution內(nèi)存。

從getMaxExecutironMemory方法可知,每個(gè)executor分配給execution的內(nèi)存為:Execution Memory = systemMaxMemory *memoryFraction(默認(rèn)0.2) * safetyFraction(默認(rèn)0.8), 默認(rèn)為 executor ***可用內(nèi)存 * 0.16。

技術(shù)專欄|Spark 靜態(tài)內(nèi)存管理詳解

Execution內(nèi)存在運(yùn)行時(shí)會(huì)被分配給運(yùn)行在JVM上的task。這里不同的是,分配給每個(gè)task的內(nèi)存并不是固定的,而是動(dòng)態(tài)的。spark不是一上來就分配固定大小的內(nèi)存塊給task,而是允許一個(gè)task占據(jù)JVM所有execution內(nèi)存。

每個(gè)JVM上的task可以最多申請至多1/N的execution內(nèi)存(N為active task的個(gè)數(shù),由spark.executor.cores指定)。如果task的申請沒有被批準(zhǔn),它會(huì)釋放一部分內(nèi)存,并且下次申請的時(shí)候,它會(huì)申請更小的一部分內(nèi)存。

注意:為了防止過多的spilling(evict)數(shù)據(jù),只有當(dāng)一個(gè)task分配到的內(nèi)存達(dá)到execution內(nèi)存1/(2N)的時(shí)候才會(huì)spill, 如果目前空閑的內(nèi)存達(dá)不到1/(2N)的時(shí)候, 內(nèi)存申請會(huì)被阻塞直到其他的taskspill掉它們的內(nèi)存。如果不這樣限制,假設(shè)當(dāng)前有一個(gè)任務(wù)占據(jù)了絕大部分內(nèi)存,那么新來的task會(huì)一直往硬盤spill數(shù)據(jù),這樣就會(huì)導(dǎo)致比較嚴(yán)重的I/O問題。

舉個(gè)例子, 某executor先啟動(dòng)一個(gè)task A,并在task B啟動(dòng)前快速占用了所有可用內(nèi)存。(B啟動(dòng)后)N變成2,task B會(huì)阻塞直到task A spill,自己可獲得1/(2N)=1/4的execution內(nèi)存。而一旦task B獲取到了1/4的內(nèi)存,A和B就都有可能spill了。

預(yù)留內(nèi)存

Spark之所以有一個(gè)SafetyFraction這樣的參數(shù),是為了避免潛在的OOM。例如,進(jìn)行計(jì)算時(shí),有一個(gè)提前未預(yù)料到的比較大的數(shù)據(jù),會(huì)導(dǎo)致計(jì)算時(shí)間延長甚至OOM, safetyFraction為storage和execution 都提供了額外的buffer以防止此類的數(shù)據(jù)傾斜。這部分內(nèi)存叫做預(yù)留內(nèi)存。

四 Storage內(nèi)存

可用的Storage內(nèi)存

該部分內(nèi)存用作對RDD的緩存(如調(diào)用cache,persist等方法),節(jié)點(diǎn)間傳輸?shù)膹V播變量。

從StaticMemoryManager的單例對象中可知,***為每個(gè)executor分配到的關(guān)于storage的內(nèi)存:

StorageMemory=systemMaxMemory*storageMemoryFraction(默認(rèn)0.6)*safetyFraction(默認(rèn)為0.9)=0.54,

也就是說 默認(rèn)分配executor ***可用內(nèi)存的 *0.54。源碼如下:

技術(shù)專欄|Spark 靜態(tài)內(nèi)存管理詳解

預(yù)留內(nèi)存

同Execution內(nèi)存中的預(yù)留部分。

Unroll

unroll是storage中比較特殊的一部分,它默認(rèn)占據(jù)總內(nèi)存的20%。

BlockManager是spark自己實(shí)現(xiàn)的內(nèi)部分布式文件系統(tǒng),BlockManager接受數(shù)據(jù)(可能從本地或者其他結(jié)點(diǎn))的時(shí)候是以iterator的形式,并且這些數(shù)據(jù)有序列化和非序列化的。需要注以下兩點(diǎn):

a) iterator在物理內(nèi)存上是不連續(xù)的,如果后續(xù)spark要把數(shù)據(jù)裝載進(jìn)內(nèi)存的話,就需要把這些數(shù)據(jù)放進(jìn)一個(gè)array(物理上連續(xù))。

b) 另外,序列化數(shù)據(jù)需要進(jìn)行展開,如果直接展開序列化的數(shù)據(jù),會(huì)造成OOM, 所以,BlockManager會(huì)逐漸的展開這個(gè)iterator,并逐漸檢查內(nèi)存里是否還有足夠的空間用來展開數(shù)據(jù)放進(jìn)array里。

技術(shù)專欄|Spark 靜態(tài)內(nèi)存管理詳解

unroll的優(yōu)先級還是比較高的,它使用的內(nèi)存空間可以從storage中借用,如果在storage中沒有現(xiàn)存的數(shù)據(jù)block,它甚至可以占據(jù)整個(gè)storage空間。如果storage中有數(shù)據(jù)block,它可以***drop掉內(nèi)存的數(shù)據(jù)是以spark.storage.unrollFraction來控制的。由圖6可知,這部分默認(rèn)為storage的20%。

注意:這個(gè)20%的空間并不是靜態(tài)保留的,而是通過drop掉內(nèi)存中的數(shù)據(jù)block來分配的。如果unroll失敗了,spark會(huì)把這部分?jǐn)?shù)據(jù)evict 到硬盤。

五 Other 部分

這片內(nèi)存用于程序本身運(yùn)行所需的內(nèi)存,以及用戶定義的數(shù)據(jù)結(jié)構(gòu)和創(chuàng)建的對象,此內(nèi)存有上面兩部分決定,默認(rèn)為0.2。

六 局限性

spark的設(shè)計(jì)文檔中指出靜態(tài)內(nèi)存有以下局限性:

(1)沒有適用于所有應(yīng)用的默認(rèn)配置,通常需要開發(fā)人員針對不同的應(yīng)用進(jìn)行不同的參數(shù)配置。比如根據(jù)任務(wù)的執(zhí)行邏輯,調(diào)整shuffle和storage內(nèi)存占比來適應(yīng)任務(wù)的需求。

(2) 這樣需要開發(fā)人員具備較高的spark原理知識(shí)。

(3) 那些不cache數(shù)據(jù)的應(yīng)用在運(yùn)行時(shí)只占用一小部分可用內(nèi)存,因?yàn)槟J(rèn)的內(nèi)存配置中,storage用去了safety內(nèi)存的60%。

概念補(bǔ)充

eviction策略:在spark技術(shù)文檔中,eviction一詞經(jīng)常出現(xiàn)。eviction并不是單純字面上驅(qū)逐的意思。說句題外話,spark我們通常都把它叫做內(nèi)存計(jì)算框架,嚴(yán)格意義來說,spark并不是內(nèi)存計(jì)算的新技術(shù)。無論是cache還是persist這類算子,spark在內(nèi)存安排上,絕大多數(shù)用的都是LRU策略(LRU可以說是一種算法,也可以算是一種原則,用來判斷如何從Cache中清除對象,而LRU就是“近期最少使用”原則,當(dāng)Cache溢出時(shí),最近最少使用的對象將被從Cache中清除)。即當(dāng)內(nèi)存不夠的時(shí)候,會(huì)evict掉最遠(yuǎn)使用過的內(nèi)存數(shù)據(jù)block。當(dāng)evict的時(shí)候,spark會(huì)將該數(shù)據(jù)塊evict到硬盤,而不是單純的拋棄掉。

無論是storage還是execution的內(nèi)存空間,當(dāng)內(nèi)存區(qū)域的空間不夠用的時(shí)候,spark都會(huì)evict數(shù)據(jù)到硬盤。

因此,如果開發(fā)人員在內(nèi)存分配上沒有合理的進(jìn)行分配,無論是在storage還是execution超過內(nèi)存的限制的時(shí)候,spark會(huì)把內(nèi)存的數(shù)據(jù)寫到硬盤。如果是storage的情況,甚至可能把內(nèi)存的數(shù)據(jù)全部寫到硬盤并丟掉。這樣做,無疑會(huì)增加系統(tǒng)調(diào)用、I/O以及重復(fù)計(jì)算的開銷。有過開發(fā)spark任務(wù)中包含大量shuffle stage的同學(xué)應(yīng)該有同感,shuffle memory不夠的時(shí)候,spill到硬盤的數(shù)據(jù)會(huì)很大,導(dǎo)致任務(wù)很慢,甚至?xí)?dǎo)致任務(wù)的各種重試***任務(wù)fail掉。這種情況建議提高shuffle memory fraction。如果是資源調(diào)度在yarn上,建議通過spark.yarn.executor.memoryOverhead提高堆外內(nèi)存,有的時(shí)候甚至?xí){(diào)到2g,3g,4g直到任務(wù)成功。spark相關(guān)優(yōu)化,請參見spark系列后續(xù)的文章。

七 參考

[1] Unified Memory Management in Spark 1.6,Andrew Or and Josh Rosen

[2]https://www.ibm.com/developerworks/cn/analytics/library/ba-cn-apache-spark-memory-management/index.html?ca=drs-&utm_source=tuicool&utm_medium=referral

[3] https:// http://spark.apache.org

[4] http://www.jianshu.com/p/e41b18a7e202

責(zé)任編輯:武曉燕 來源: 今日頭條
相關(guān)推薦

2018-12-18 14:37:26

Spark內(nèi)存管理

2017-04-01 14:01:50

Apache Spar內(nèi)存管理

2018-08-09 11:06:39

Apache Spar內(nèi)存模型

2011-06-03 10:19:59

iphone Objective-

2019-04-17 14:44:42

Spark內(nèi)存源碼

2019-10-10 16:20:23

spark內(nèi)存管理

2011-07-19 15:37:13

Oracle 10g內(nèi)存管理PGA

2010-09-26 13:23:13

JVM內(nèi)存管理機(jī)制

2018-06-06 08:28:37

Spark內(nèi)存管理

2011-07-01 10:16:08

C++內(nèi)存管理

2010-12-10 15:40:58

JVM內(nèi)存管理

2011-06-29 17:20:20

Qt 內(nèi)存 QOBJECT

2024-03-26 00:33:59

JVM內(nèi)存對象

2020-08-18 19:15:44

Redis內(nèi)存管理

2018-05-31 20:49:50

Spark堆內(nèi)內(nèi)存優(yōu)化機(jī)制

2009-09-02 09:23:26

.NET內(nèi)存管理機(jī)制

2022-12-28 08:52:15

編譯器自動(dòng)內(nèi)存管理

2018-05-10 09:51:39

Spark內(nèi)存Hadoop

2011-08-22 11:07:16

IOS 開發(fā)多核內(nèi)存

2009-08-28 14:09:19

C#靜態(tài)類
點(diǎn)贊
收藏

51CTO技術(shù)棧公眾號