Spark 中OOM的現象 原因 解決方案和總結

2021-10-08 08:04:27 字數 3125 閱讀 9702

參考:

spark的executor的container記憶體有兩大部分組成:堆外記憶體和executor記憶體。

堆外記憶體

有spark.yarn.executor.memeoryoverhead引數設定。如果沒有設定,則使用

val executormemoryoverhead = sparkconf.

getint

("spark.yarn.executor.memoryoverhead"

,math.

max(

(memory_overhead_factor

* executormemory)

.toint,

memory_overhead_min

))

memory_overhead_factor = 0.10預設為0.01;

// 最終分配的executor 記憶體為 兩部分的和

val executormem = args.executormemory + executormemoryoverhead

來獲得。

spark在乙個executor中的記憶體分為三部分:

1、execution塊,shuffle的資料也會先快取在這個記憶體中,滿了再寫入磁碟中、排序、map的過程也是在這個記憶體中執行的、聚合、計算的記憶體。

2、storage塊,用於集群中快取rdd和傳播內部資料的記憶體(cache、persist資料的地方、廣播變數)

3、other塊,程式執行時預留給自己的記憶體,如spark程式的物件。

execution塊和storage塊佔executor的大部分,而other占有一小部分。在spark1.6之後,execution記憶體和storage記憶體可以相互借用,提高了記憶體的spark中記憶體的使用率,同時也減少了omm的情況。

**在實際分配executor記憶體的計算,需要涉及在yarn上的部署模式**
var executormemory =

1024

// 預設值,1024mb

val memory_overhead_factor =

0.10

// overhead 比例引數,預設0.1

val memory_overhead_min =

384val executormemoryoverhead =sparkconf.

getint

("spark.yarn.executor.memoryoverhead"

,math.

max(

(memory_overhead_factor * executormemory)

.toint, memory_overhead_min)

)// 假設有設定引數,即獲取引數,否則使用executormemoryoverhead 的預設值

val executormem = args.executormemory + executormemoryoverhead

// 最終分配的executor 記憶體為 兩部分的和

提交的指令碼:spark-submit --master yarn-cluster --name test --driver-memory 6g --executor-memory 6g

總得大小應該為6144mb+612mb=6756mb

然而實際的開銷為7168,這是為什麼呢?

這會涉及到規整化因子

為了易於管理資源和排程資源,hadoop yarn內建了資源規整化演算法,它規定了最小可申請資源量、最大可申請資源量和資源規整化因子,如果應用程式申請的資源量小於最小可申請資源量,則yarn會將其大小改為最小可申請量,也就是說,應用程式獲得資源不會小於自己申請的資源,但也不一定相等;如果應用程式申請的資源量大於最大可申請資源量,則會丟擲異常,無法申請成功;規整化因子是用來規整化應用程式資源的,應用程式申請的資源如果不是該因子的整數倍,則將被修改為最小的整數倍對應的值,公式為:

ceil(a/b)*b,其中a是應用程式申請的資源,b為規整化因子。

比如,在yarn-site.xml中設定,相關引數如下:

yarn.scheduler.minimum-allocation-mb:最小可申請記憶體量,預設是1024

yarn.scheduler.minimum-allocation-vcores:最小可申請cpu數,預設是1

yarn.scheduler.maximum-allocation-mb:最大可申請記憶體量,預設是8096

yarn.scheduler.maximum-allocation-vcores:最大可申請cpu數,預設是4

對於規整化因子,不同排程器不同,具體如下:

fifo和容量排程器(capacity scheduler),規整化因子等於最小可申請資源量,不可單獨配置。

fair scheduler:規整化因子通過引數yarn.scheduler.increment-allocation-mb和yarn.scheduler.increment-allocation-vcores設定,預設是1024和1。

比如yarn的最小可申請資源記憶體量為1024,規整因子是1024,如果乙個應用程式申請1500記憶體,則會得到2048,如果規整因子是512,則得到的記憶體1536。

所以最終分配的記憶體為:ceil(6756/1024)*1024=7168

小結:雖然spark中用executor-memory引數控制那個executor的記憶體,但是,實際分配多少記憶體,還有一定的處理機制,需要跟蹤原始碼來發掘

這種溢位的原因:是在單個map中產生了大量的物件導致的。

**解決方法:**通過減少每個task的大小來減少executor記憶體中的數量,具體做法是在呼叫map操作前先呼叫repartition方法,增大分割槽數來減少每個分割槽的大小,再傳入map中進行操作。

資料不平衡除了可能導致記憶體溢位外,也可能導致效能的問題,解決方法和上面的類似。

shuffle記憶體溢位的情況可以說都是shuffle後,shuffle會產生資料傾斜,少數的key記憶體非常的大,它們都在同乙個executor中計算,導致運算量加大甚至會產生oom。

什麼是oom,常見造成oom的原因,及解決方法

一 什麼是oom oom就是我們常說的記憶體溢位,它是指需要的記憶體空間大於系統分配的記憶體空間,oom後果就是專案程式crash 二 常見造成oom的原因 1.記憶體洩露造成 2.載入的檔案或者過大造成 三 解決方案 記憶體洩露是造成記憶體溢位的乙個原因,所以避免記憶體洩露的那些方法都適用於記憶體...

spark產生的原因

一 spark產生的目的 spark產生 為了替代mapreduce,解決mapreduce計算短板 hadoop生態體系 hdfs zokeeper mareduce hive hbase storm mahot 其他 工具 spark體系 hdfs zokeeper spark hbase st...

出現亂碼現象的原因分析

首先我們知道知道utf 8編碼俗稱 萬國碼 我們能接觸到的編碼utf 8都囊括在內,所以我們也常用這一編碼集,出現亂碼情況也可以從這入手。1.資料庫建立的時候我們一般會設定編碼,通常也有預設形式。出現亂碼我們可以檢查是否為utf 8,通過控制台等檢視表中是否出現亂碼,出現了就可能需要檢查修改資料庫的...