spark2020面試題

BlackEyes_SGC發表於2020-11-19

一、RDD

1.spark中的RDD是什麼,有哪些特性
答:RDD(Resilient Distributed Dataset)叫做分散式資料集,是spark中最基本的資料抽象,它代表一個不可變,可分割槽,裡面的元素可以平行計算的集合。
Resilient:表示彈性的,彈性表示
Dataset:就是一個集合,用於存放資料的
Destributed:分散式,可以並行在叢集計算
** 2. 抽象彈性分散式資料集對於Spark來說的彈性計算到底提現在什麼地方?**
1)存和磁碟資料這兩種儲存方式的切換
Spark 可以使用 persist 和 cache 方法將任意 RDD 快取到記憶體或者磁碟檔案系統中。資料會優先儲存到記憶體中,當記憶體不足以存放RDD中的資料的時候,就會持久化到磁碟上。這樣,就可以最大化的利益記憶體以達到最高的計算效率;同時又有磁碟作為兜底儲存方案以確保計算結果的正確性。
2)基於Linage的高效容錯機制
Linage是用於記錄RDD的父子依賴關係,子RDD會記錄父RDD,且各個分片之間的資料互不影響。當出現錯誤的時候,只需要恢復單個Split的特定部分即可。
3)Task失敗自動重試,Stage失敗自動重試
TaskScheduler從每一個Stage的DAGScheduler中獲取TaskSet,執行並校驗是否存在故障。如果存在故障則會重試指定測試。
Stage物件可以記錄並跟蹤多個StageInfo,預設的重試次數也是4次。且可以直接執行計算失敗的階段,值計算失敗的資料分片。
4)資料排程彈性
3. RDD有哪些特性

  1. 分割槽
    每一個 RDD 包含的資料被儲存在系統的不同節點上,是由很多分割槽組成的,操作RDD的時候,對RDD裡面的每一個分割槽進行操作。而這些操作真正的會分發到每臺機器上,並且擁有容錯機制。
    在物理儲存中,每個分割槽指向一個儲存在記憶體或者硬碟中的資料塊 (Block) ,其實這個資料塊就是每個 task 計算出的資料塊,它們可以分佈在不同的節點上。
    所以,RDD 只是抽象意義的資料集合,分割槽內部並不會儲存具體的資料,只會儲存它在該 RDD 中的 index,通過該 RDD 的 ID 和分割槽的 index 可以唯一確定對應資料塊的編號,然後通過底層儲存層的介面提取到資料進行處理。
    在叢集中,各個節點上的資料塊會盡可能的儲存在記憶體中,只有當記憶體沒有空間時才會放入硬碟儲存,這樣可以最大化的減少硬碟 IO 的開銷。
  2. 不可變
    不可變性是指每個 RDD 都是隻讀的,它所包含的分割槽資訊是不可變的。由於已有的 RDD 是不可變的,所以我們只有對現有的 RDD 進行轉化 (Transformation) 操作,才能得到新的 RDD ,一步一步的計算出我們想要的結果。
    這樣會帶來這樣的好處:我們在 RDD 的計算過程中,不需要立刻去儲存計算出的資料本身,我們只要記錄每個 RDD 是經過哪些轉化操作得來的,即:依賴關係,這樣一方面可以提高計算效率,一方面是錯誤恢復會更加容易。如果在計算過程中,第 N 步輸出的 RDD 的節點發生故障,資料丟失,那麼可以根據依賴關係從第 N-1 步去重新計算出該 RDD,這也是 RDD 叫做"彈性"分散式資料集的一個原因,也會容錯機制。
  3. 並行操作
    因為 RDD 的分割槽特性,所以其天然支援並行處理的特性。即不同節點上的資料可以分別被處理,然後生成一個新的 RDD。
    4. RDD特性考察
    下面哪個不是 RDD 的特點 (C )
    A. 可分割槽 B 可序列化 C 可修改 D 可持久化
    5. 惰性機制
    RDD的Transformation操作都是惰性求值的。惰性求值即當對RDD呼叫轉化操作(例如呼叫map())時,操作不會立即執行。相反,Spark會在內部記錄下所要求執行的操作的相關資訊。
    6. 惰性機制考察
    A df.count() df.cahce() df.count()
    B df.cahce() df.count() df.count()
    A、B兩個計算那個用時短?
    7. RDD和dataFrame的區別
    DataFrame 和 RDD 最大的區別 (B )
    A.科學統計支援 B.多了 schema
    C.儲存方式不一樣 D.外部資料來源支援

二、driver、Executor相關

1. driver的功能是什麼?
1)一個Spark作業執行時包括一個Driver程式,也是作業的主程式,具有main函式,並且有SparkContext的例項,是程式的人口點;
2)功能:負責向叢集申請資源,向master註冊資訊,負責了作業的排程,負責作業的解析、生成Stage並排程Task到Executor上。
2. spark的有幾種部署模式,每種模式特點?
1)本地模式:Spark不一定非要跑在hadoop叢集,可以在本地,起多個執行緒的方式來指定。
2)Spark on yarn模式:分散式部署叢集,資源和任務監控交給yarn管理,但是目前僅支援粗粒度資源分配方式,包含cluster和client執行模式,cluster適合生產,driver執行在叢集子節點,具有容錯功能,client適合除錯,dirver執行在客戶端
3)Spark On Mesos模式

三、spark儲存

1. RDD持久化
Spark 中一個很重要的能力是將資料持久化(或稱為快取),在多個操作間都可以訪問這些持久化的資料。當持久化一個RDD時,每個節點的其它分割槽都可以使用RDD在記憶體中進行計算,在該資料上的其他action操作將直接使用記憶體中的資料。這樣會讓以後的 action 操作計算速度加快(通常執行速度會加速 10 倍)。快取是迭代演算法和快速的互動式使用的重要工具。
RDD 可以使用 persist() 方法或 cache() 方法進行持久化。資料將會在第一次 action 操作時進行計算,並快取在節點的記憶體中。Spark 的快取具有容錯機制,如果一個快取的 RDD 的某個分割槽丟失了,Spark 將按照原來的計算過程,自動重新計算並進行快取。
在 shuffle 操作中(例如 reduceByKey),即便是使用者沒有呼叫 persist 方法,Spark 也會自動快取部分中間資料。這麼做的目的是,在 shuffle 的過程中某個節點執行失敗時,不需要重新計算所有的輸入資料。如果使用者想多次使用某個 RDD,強烈推薦在該 RDD 上呼叫 persist 方法。
2. Spark有幾種持久化儲存級別如下
1.MEMORY_ONLY:使用未序列化的Java物件格式,將資料儲存在記憶體中。如果記憶體不夠存放所有的資料,則資料可能就不會進行持久化。那麼下次對這個RDD執行運算元操作時,那些沒有被持久化的資料,需要從源頭處重新計算一遍。這是預設的持久化策略,使用cache()方法時,實際就是使用的這種持久化策略。
2.MEMORY_AND_DISK:使用未序列化的Java物件格式,優先嚐試將資料儲存在記憶體中。如果記憶體不夠存放所有的資料,會將資料寫入磁碟檔案中,下次對這個RDD執行運算元時,持久化在磁碟檔案中的資料會被讀取出來使用。
3.MEMORY_ONLY_SER:基本含義同MEMORY_ONLY。唯一的區別是,會將RDD中的資料進行序列化,RDD的每個partition會被序列化成一個位元組陣列。這種方式更加節省記憶體,從而可以避免持久化的資料佔用過多記憶體導致頻繁GC。
4.MEMORY_AND_DISK_SER:基本含義同MEMORY_AND_DISK。唯一的區別是,會將RDD中的資料進行序列化,RDD的每個partition會被序列化成一個位元組陣列。這種方式更加節省記憶體,從而可以避免持久化的資料佔用過多記憶體導致頻繁GC。
5.DISK_ONLY:使用未序列化的Java物件格式,將資料全部寫入磁碟檔案中。
6.MEMORY_ONLY_2, MEMORY_AND_DISK_2, 等等:對於上述任意一種持久化策略,如果加上字尾_2,代表的是將每個持久化的資料,都複製一份副本,並將副本儲存到其他節點上。這種基於副本的持久化機制主要用於進行容錯。假如某個節點掛掉,節點的記憶體或磁碟中的持久化資料丟失了,那麼後續對RDD計算時還可以使用該資料在其他節點上的副本。如果沒有副本的話,就只能將這些資料從源頭處重新計算一遍了。
3. 持久化儲存級別考察
預設的儲存級別 (A )
A MEMORY_ONLY B MEMORY_ONLY_SER
C MEMORY_AND_DISK D MEMORY_AND_DISK_SER
下列哪個不是 RDD 的快取方法 (C )
A persist() B Cache()
C Memory()
4. spark中cache和persist的區別

四、資料傾斜

1. 資料傾斜危害
單個或少數的節點資料量特別大,但一個 Stage 所耗費的時間,是由最慢的那個 Task 決定,所以資料傾斜會導致兩個後果:

  1. OOM(單或少數的節點);
  2. 拖慢整個Job執行時間(其他已經完成的節點都在等這個還在做的節點)。
    2. 資料傾斜的現象
    當發現如下現象時,十有八九是發生資料傾斜了:
    • 絕大多數 task 執行得都非常快,但個別 task 執行極慢,整體任務卡在某個階段不能結束。
    • 原本能夠正常執行的 Spark 作業,某天突然報出 OOM(記憶體溢位)異常。
    3. 導致Spark資料傾斜的本質
    在進行 shuffle 的時候,必須將各個節點上相同的 key 拉取到某個節點上的一個 task 來進行處理,比如按照 key 進行聚合或 join 等操作。此時如果某個 key 對應的資料量特別大的話,就會發生資料傾斜。比如大部分 key 對應10條資料,但是個別 key 卻對應了100萬條資料,那麼大部分 task 可能就只會分配到10條資料,然後1秒鐘就執行完了;但是個別 task 可能分配到了100萬資料,要執行一兩個小時。
  3. 定位最慢的Task所處的原始碼位置
    步驟一:看資料傾斜發生在哪個stage。yarn-client模式下檢視本地log或Spark Web UI中當前執行的是哪個stage;yarn-cluster模式下,通過Spark Web UI檢視執行到了哪個Stage。
    主要看最慢的Stage各task分配的資料量,來確定是否是資料傾斜。
    步驟二:根據Stage劃分,推算傾斜發生的程式碼(必然有Shuffle類運算元)。
    根據stage劃分原理,推算出來發生傾斜的那個stage對應程式碼中的哪一部分,這部分程式碼中肯定會有一個shuffle類運算元。簡單實用方法:只要看到shuffle類運算元或Spark SQL的SQL語句會有Shuffle類的運算元的句子,就可以知道該地方劃分為前後兩個Stage。(用Python的PySpark介面,Spark Web UI會檢視task在原始碼中的行數。)
  4. 解決方案

五、寬窄依賴、Stage、Job、task

1. 談談spark中的寬窄依賴
依賴關係,記錄了該 RDD 的計算過程,也就是說這個 RDD 是通過哪個 RDD 經過怎麼樣的轉化操作得到的。窄依賴允許子 RDD 的每個分割槽可以被並行處理產生,而且支援在同一個節點上鍊式執行多條指令,無需等待其它父 RDD 的分割槽操作。
Spark 區分寬窄依賴的原因有兩點:

  1. 窄依賴支援在同一節點上進行鏈式操作。相反,款依賴需要所有父分割槽都是可用的。
  2. 從失敗恢復的角度考慮,窄依賴失敗恢復更有效,因為只要重新計算丟失的父分割槽即可,而寬依賴涉及到 RDD 的各級多個父分割槽。
  3. 寬窄依賴考察
    下面哪個操作是窄依賴 (B )
    A join B filter
    C group D sort
    12.下面哪個操作肯定是寬依賴 (C )
    A map B flatMap
    C reduceByKey D sample
    3. Job、Stage、Task劃分依據
    Job:由一個 rdd 的 action 觸發的動作,當需要執行一個 rdd 的 action 的時候,會生成一個 job,一個job生成多個stage。
    Stage:stage 是一個 job 的組成單位,就是說,一個 job 會被切分成 1 個或 1 個以上的 stage,然後各個 stage 會按照執行順序依次執行。而一個stage劃分成多個tsak。
    目前有兩個劃分 stage 的依據:
    • 當觸發 rdd 的 action 時
    • 當觸發 rdd 的 shuffle 操作時
    Task:即 stage 下的一個任務執行單元,一般來說,一個 rdd 有多少個 partition,就會有多少個 task,因為每一個 task 只是處理一個 partition 上的資料。
    4. Job、Stage、Task考察
    Stage 的 Task 的數量由什麼決定 (A )
    A Partition B Job C Stage D TaskScheduler

六、Spark效能優化

七、併發

八、pyspark內建函式、常用運算元

1. 概述一下spark中的常用運算元區別(map,mapPartitions,foreach,foreachPatition)
答:map:用於遍歷RDD,將函式應用於每一個元素,返回新的RDD(transformation運算元)
foreach:用於遍歷RDD,將函式應用於每一個元素,無返回值(action運算元)
mapPatitions:用於遍歷操作RDD中的每一個分割槽,返回生成一個新的RDD(transformation運算元)
foreachPatition:用於遍歷操作RDD中的每一個分割槽,無返回值(action運算元)
總結:一般使用mapPatitions和foreachPatition運算元比map和foreach更加高效,推薦使用。

九、常見OOM型別報錯,及解決辦法

1、報錯:啟動時發現報錯:java.lang.IllegalArgumentException: Required executor memory (102400+4096 MB) is above the max threshold (28672 MB) of this cluster! Please check the values of ‘yarn.scheduler.maximum-allocation-mb’ and/or ‘yarn.nodemanager.resource.memory-mb’.
原因:提交任務時,啟動失敗,memoryOverhead+memory > (Max)MonitorMemory。
解決: 減小兩個引數的值即可。
2、報錯::Driver中發現報錯:YarnAllocator: Container killed by YARN for exceeding memory limits. X GB of Y GB physical memory used. Consider boosting spark.yarn.executor.memoryOverhead.
原因:執行時失敗,memoryOverhead+memory > MonitorMemory
解決:通過–conf spark.sql.shuffle.partitions=XXX增大partitions個數;或增大overhead/memory的大小,不超過(Max)MonitorMemory即可。若已經到max仍然報錯,可以減少單個Executor的併發數(cores),增大Executor數量。
3、報錯:Excutor日誌中發現報錯:java.lang.OutOfMemoryError: Java heap space 、org.apache.spark.shuffle.FetchFailedException: Java heap space、 Container killed on request. Exit code is 143
原因:程式執行時所需記憶體 > memory。一般是因為處理資料量或者快取的資料量較大,已有記憶體不足並且記憶體分配速度 > GC回收速度導致。
解決:增大memory、減少單個Executor的併發數(cores)、減少不必要的cache操作、儘量不要對比較大的資料做broadcast、儘量避免shuffle運算元或者對程式邏輯/底層資料進行優化。
4、報錯:
org.apache.spark.shuffle.FetchFailedException: java.io.FileNotFoundException: …shuffle_xxx.index (No such file or directory)
原因:OOM導致shuffle獲取檔案失敗,此報錯只是一個結果,原因是由於上述OOM導致,請詳細檢視日誌是否有OOM的關鍵字。
解決:找到OOM關鍵字,解決OOM問題即可。 或者開啟external shuffle service, --conf spark.shuffle.service.enabled=true
5、報錯:
org.apache.hadoop.ipc.RemoteException(org.apache.hadoop.ipc.StandbyException): Operation category WRITE is not supported in state standby
原因:訪問(讀、寫)hdfs,namenode(hdfs的管理節點)較忙壓力較大時,spark超過一定時間會自動切換到namenod的standby節點嘗試訪問。standby會返回這個異常資訊,然後spark會自動連線active節點。 所以該報錯只是hdfs較忙的一個提示,並不是spark執行報錯。
解決:繼續等待即可,或者聯絡集市管理人員諮詢為什麼hfds壓力較大。
6
報錯:YarnScheduler: Initial job has not accepted any resources; check your cluster UI to ensure that workers are registered and have sufficient resources
ERROR FileFormatWriter: Aborting job null.
java.util.concurrent.TimeoutException: Futures timed out after [300 seconds]
原因: driver啟動後提交job,超過300s(預設值)沒有啟動Executor會導致app超時失敗
解決: 1. 調整任務執行時間,選擇資源充足的時段執行。 2. 調整超時時間 --conf spark.sql.broadcastTimeout=900 (15分鐘 或者其他值)

十、叢集資源

  • 由於spark節點分Driver(只有一個)和Executor(一般有多個)兩種概念。但兩種節點記憶體模型一樣,且OOM常發生在Executor。
  • 每個Spark Executor會單獨佔用一個Container,單個Container記憶體的上限,就是Spark Executor記憶體上限,後面稱此值為MonitorMemory。
  • MonitorMemory = spark.yarn.executor.memoryOverhead + spark.executor.memory。我們叢集中,memoryOverhead設定成固定的4G,使用者也可以通過引數自己調整。
  • spark.executor.memory 需要使用者自己設定。我們的叢集中,建議 1 excutor core 對應 2~4G executor.memory。

十一、檢視應用

yarn application

  • -list列出所有 application 資訊
    示例:yarn application -list
  • -appStates跟-list一起使用,用來篩選不同狀態的application,多個用","分隔;所有狀態ALL,NEW,NEW_SAVING,SUBMITTED,ACCEPTED,RUNNING,FINISHED,FAILED,KILLED
    示例:yarn application -list -appStates RUNNING
  • -appTypes跟-list一起使用,用來篩選不同型別的application,多個用","分隔;如MAPREDUCE。
    示例:yarn application -list -appTypes MAPREDUCE
  • -kill殺死一個application,需要指定一個Application ID。
    示例:yarn application -kill application_1526100291229_206393
  • -status列出某個application 的狀態
    示例:yarn application -status application_1526100291229_206393
  • -movetoqueue移動application到其他的queue,不能單獨使用。
  • -queue與movetoqueue命令一起使用,指定移動到哪個queue。
    示例:yarn application -movetoqueue application_1526100291229_206393 -queue other

Linux

  • “|” 用來將前一個命令的標準輸出傳遞到下一個命令的標準輸入。
  • wc指令我們可以計算檔案的Byte數、字數、或是列數。-l或–lines 只顯示行數,-w或–words 只顯示字數。
    例子:
    yarn application -list |grep mart_vdp |wc -l
    yarn application -list |grep mart_vdp |grep caochengxi | wc -l

相關文章