Spark之OOM解決方案

2020-09-05 大數據私房菜

你在工作當中有遇到內存溢出問題嗎?你是如何解決的?


oom通常出現在execution內存中,因為storage這塊內存在放滿之後,會直接丟棄內存中舊的數據,對性能有點影響但不會導致oom。


一 OOM原因


  • Driver 內存不足

driver端生成大對象

collect數據收集導致


  • Executor 內存不足

map 類操作產生大量數據包括 map,flatMap,filter,mapPartitions 等

shuffle 後產生數據傾斜


二 Driver 內存不足


1.用戶在Dirver端生成大對象,比如創建了一個大的集合數據結構


  • 將大對象轉換成Executor端加載,比如調用sc.textfile
  • 評估大對象佔用的內存,增加dirver-memory的值

--driver-memory MEM Memory for driver (e.g. 1000M, 2G) (Default: 1024M).


2.collect


本身不建議將大的數據從executor端,collect回來。建議將driver端對collect回來的數據所作的操作,轉換成executor端rdd操作

若無法避免,估算collect需要的內存,相應增加driver-memory的值

rdd = sc.parallelize(range(100))rdd.flatMap(lambda x: [&39;%x*50 for _ in range(100000)]).collect() 39;%d& 分區輸出


三 Executor 內存不足


1.增加 Executor 內存


--executor-memory MEM Memory per executor (e.g. 1000M, 2G) (Default: 1G).


2.map過程產生大量對象導致內存溢出


這種溢出的原因是在單個map中產生了大量的對象導致的,例如:rdd.map(x=>for(i <- 1 to 10000) yield i.toString),這個操作在rdd中,每個對象都產生了10000個對象,這肯定很容易產生內存溢出的問題。針對這種問題,在不增加內存的情況下,可以通過減少每個Task的大小,以便達到每個Task即使產生大量的對象Executor的內存也能夠裝得下。具體做法可以在會產生大量對象的map操作之前調用repartition方法,分區成更小的塊傳入map。例如:rdd.repartition(10000).map(x=>for(i <- 1 to 10000) yield i.toString)。


3.數據傾斜導致內存溢出


解決方案:Spark數據傾斜解決方案


4.coalesce調用導致內存溢出


因為hdfs中不適合存小問題,所以Spark計算後如果產生的文件太小,我們會調用coalesce合併文件再存入hdfs中。但是這會導致一個問題,例如在coalesce之前有100個文件,這也意味著能夠有100個Task,現在調用coalesce(10),最後只產生10個文件,因為coalesce並不是shuffle操作,這意味著coalesce並不是按照我原本想的那樣先執行100個Task,再將Task的執行結果合併成10個,而是從頭到位只有10個Task在執行,原本100個文件是分開執行的,現在每個Task同時一次讀取10個文件,使用的內存是原來的10倍,這導致了OOM。解決這個問題的方法是令程序按照我們想的先執行100個Task再將結果合併成10個文件,這個問題同樣可以通過repartition解決,調用repartition(10),因為這就有一個shuffle的過程,shuffle前後是兩個Stage,一個100個分區,一個是10個分區,就能按照我們的想法執行。


5.shuffle後內存溢出


shuffle內存溢出的情況可以說都是shuffle後,單個文件過大導致的。在Spark中,join,reduceByKey這一類型的過程,都會有shuffle的過程,在shuffle的使用,需要傳入一個partitioner,大部分Spark中的shuffle操作,默認的partitioner都是HashPatitioner,默認值是父RDD中最大的分區數,這個參數通過spark.default.parallelism控制(在spark-sql中用spark.sql.shuffle.partitions) , spark.default.parallelism參數只對HashPartitioner有效,所以如果是別的Partitioner或者自己實現的Partitioner就不能使用spark.default.parallelism這個參數來控制shuffle的並發量了。如果是別的partitioner導致的shuffle內存溢出,就需要從partitioner的代碼增加partitions的數量。


6.standalone 模式資源分配不均


在standalone的模式下如果配置了--total-executor-cores 和 --executor-memory 這兩個參數,但是沒有配置--executor-cores這個參數的話,就有可能導致,每個Executor的memory是一樣的,但是cores的數量不同,那麼在cores數量多的Executor中,由於能夠同時執行多個Task,就容易導致內存溢出的情況。這種情況的解決方法就是同時配置--executor-cores或者spark.executor.cores參數,確保Executor資源分配均勻。


7.在RDD中,共用對象能夠減少OOM的情況


rdd.flatMap(x=>for(i <- 1 to 1000) yield (&34;,&34;))導致OOM,但是在同樣的情況下,使用rdd.flatMap(x=>for(i <- 1 to 1000) yield &34;+&34;)就不會有OOM的問題,

這是因為每次(&34;,&34;)都產生一個Tuple對象,

而&34;+&34;,不管多少個,都只有一string個對象,指向常量池。

相關焦點

  • 各種OOM代碼樣例及解決方法
    針對目前大家對OOM的類型不太熟悉,那麼來總結一下各種OOM出現的情況以及解決方法。把各種OOM的情況列出來,然後逐一進行代碼編寫復現和提供解決方法。1.package oom;import java.util.ArrayList;import java.util.List;import java.util.concurrent.TimeUnit;public class HeapOOM {    static&
  • Spark 數據傾斜及其解決方案
    本文從數據傾斜的危害、現象、原因等方面,由淺入深闡述Spark數據傾斜及其解決方案。(3)解決方案調整並行度。一般是增大並行度,但有時如減小並行度也可達到效果。(4)優勢實現簡單,只需要參數調優。可用最小的代價解決問題。一般如果出現數據傾斜,都可以通過這種方法先試驗幾次,如果問題未解決,再嘗試其它方法。
  • Spark數據傾斜之騷操作解決方案
    請接下往下看症狀以及原因比如一個spark任務中,絕大多數task任務運行速度很快,但是就是有那麼幾個task任務運行極其緩慢,慢慢的可能就接著報內存溢出的問題了,那麼這個時候我們就可以認定是數據傾斜了.為什麼會這種情況呢?
  • mysql oom案例分析
    task regardless of the root bonus and * oom_score_adj (oom_score_adj can't be OOM_SCORE_ADJ_MIN here).
  • 郭健:Linux內存管理系統參數配置之OOM(內存耗盡)
    內核中sysctl_panic_on_oom變量是和/proc/sys/vm/panic_on_oom對應的,主要的判斷邏輯如下:3、oom_dump_tasks當系統的內存出現OOM狀況,無論是panic還是啟動OOM killer,做為系統管理員,你都是想保留下線索,找到OOM的root cause,例如dump系統中所有的用戶空間進程關於內存方面的一些信息,包括:進程標識信息、該進程使用的total virtual memory信息、該進程實際使用物理內存(我們又稱之為
  • 大數據:Spark數據傾斜解決方案_提高reduce並行度
    大數據:Spark數據傾斜解決方案_提高reduce並行度解決方案二:過濾導致傾斜的key如果在Spark作業中允許丟棄某些數據,那麼可以考慮將可能導致數據傾斜的key進行過濾,濾除可能導致數據傾斜的key對應的數據,這樣,在Spark作業中就不會發生數據傾斜了。
  • 兩分鐘學Java——應用故障之堆溢出OOM實戰
    /oom.out HeapMemUseTest</code><button>複製</button>其中的參數代表的意義為:-Xmx和-Xms分別是用於指定該Java進程初使化的最小堆內存以及可以使用的最大堆內存的,這裡設置為
  • 如何快速學習spark
    spark它是發源於美國的加州大學伯克利分校amplab集群計算平臺的,基於內存計算的,時速非常快,性能比Hadoop快100陪以上,它可以流處理、圖計算、還有很多的計算範式,我個人認為spark是個全能的選手,但是隨著技術的快速發展,現在又出現Flink,它和spark是一個競爭對手了,今天我們主要講spark,後續我會再分享Flink的知識。
  • 解決SparkStreaming推測機制存在的數據傾斜問題
    過程在尋找這個問題答案的過程中,老劉正好在學習spark框架的實時計算模塊SparkStreaming,它裡面就有一個非常經典的問題,關於推測機制的!什麼是推測機制?如果有很多個task都在運行,很多task一下就完成了自己的任務,但是有一個task運行的很慢。在實時計算任務中,如果對實時性要求比較高,就算是兩三秒也要在乎這些。
  • 手把手教你在本機安裝spark
    本文轉載自【微信公眾號:五角錢的程式設計師,ID:xianglin965】,經微信公眾號授權轉載,如需轉載與原文作者聯繫今天是spark系列的第一篇文章。最近由於一直work from home節省了很多上下班路上的時間,加上今天的LeetCode的文章篇幅較小,所以抽出了點時間加更了一篇,和大家分享一下最近在學習的spark相關的內容。
  • 億萬級海量數據去重軟方法,spark/flink/mr等通用
    某一天,你公司突然業務發展發展起來,數據量慢慢暴漲,你會突然發現之前的count distinct去重經常oom或是龜速出數據。上來一股腦加內存!加!果斷加!某一天你老闆要你在原來按天的uv加一個月uv、年uv,這時你慌了。只會說「老闆!加機器,內存不夠!」。老闆說:「算個uv你就想騙我錢?你明天不用來上班了!」
  • 快手自研OOM解決方案KOOM今日宣布開源
    近日,快手宣布開源KOOM,成為行業首個開源線上內存溢出(Out of Memory,以下簡稱OOM)問題解決方案的網際網路企業。據介紹,KOOM是在客戶端完成內存監控後,將解析報告上傳到雲端,傳輸文件大小僅為KB級,運行時用戶無感知,對流量基本無影響,適合大規模普及應用,目前該方案已在快手全量業務中應用,OOM率降低了80%以上,效果顯著。
  • 快手自研OOM解決方案KOOM今日宣布開源
    近日,快手宣布開源KOOM,成為行業首個開源線上內存溢出(Out of Memory,以下簡稱OOM)問題解決方案的網際網路企業。據介紹,KOOM是在客戶端完成內存監控後,將解析報告上傳到雲端,傳輸文件大小僅為KB級,運行時用戶無感知,對流量基本無影響,適合大規模普及應用,目前該方案已在快手全量業務中應用,OOM率降低了80%以上,效果顯著。
  • 聊一聊Spark對大數據生態圈的影響
    無論是Hive還是Mapreduce,底層跑的都是Mapreduce的代碼,與之類似的還有一個工具叫pig,Pig和Hive只是語法不一樣,它們都有自己的一套語言,都會轉換成為mapreduce去執行。
  • 故障分析 | MySQL OOM 故障應如何下手
    簡單來講,oom-killer 的原則就是損失最小、收益最大,因此它會讓殺死的進程數儘可能小、釋放的內存儘可能大。在資料庫伺服器上,MySQL 被分配的內存一般不會小,因此容易成為 oom-killer 選擇的對象。  「既然發生了 OOM,那必然是內存不足,內存不足這個問題產生原因很多。
  • 在 K8S 上運行 Spark 的最佳實踐和陷阱
    的結合是出現在spark 2.3版本以後的事情,在此之前有幾種方式。第四種是Kubernetes,現在大家也逐漸的把spark跑在k8s上面。Yarn提供一個全局的spark版本,包括python的版本,全局的包的依賴,缺少環境隔離。而k8s是完全的環境隔離,每一個應用可以跑在完全不同的環境、版本等。Yarn的包管理方案是上傳依賴包到HDFS。K8s的包管理方案是自己管理鏡像倉庫,將依賴包打入image中,支持包依賴管理,將包上傳到 OSS/HDFS,區分不同級別任務,混合使用以上兩種模式。
  • 操作練習-Spark on Yarn
    承接上一篇文檔《》將spark應用運行在yarn集群上 官網地址:http://spark.apache.org/docs/2.0.2/running-on-yarn.html1.查了一下是因為內存分配不夠導致的yarn強行關閉往yarn-site.xml中加入 <property><name>yarn.nodemanager.vmem-check-enabled</name><value>false</value></property>重啟hadoop即可解決
  • sparksql序列化異常
    在sparksql中顯示的指定了mapjoin,導致廣播的數據量太大,導致序列化超過指定大小。To avoid this, increase spark.kryoserializer.buffer.max value.
  • SPARK RDD 介紹
    2、一個計算每個分區的函數,spark中RDD的計算是以分片為單位的,每個RDD都會實現compute函數以達到這個目的,compute函數會對迭代器進行複合,不需要保存每次計算的結果。 4、一個Partitinoner,即RDD的分片函數,當期的spark中實現了兩種類型的分片函數,一個是基於哈希的HashPartitioner,另一個是基於範圍的RangerPartionner,只有對於key-value的RDD才會有Partitonner,非key-value的RDD的Parititionner的值None,Partitioner函數不但解決了RDD本身分片的數量