參考:
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,通過控制台等檢視表中是否出現亂碼,出現了就可能需要檢查修改資料庫的...