Spark 經典面試題彙總《一》

碼農談IT發表於2023-02-27


大家好我是球球,面試的季節又要到了,球球給大家總結了一些Spark的經典面試題。


1你是怎麼理解Spark,它的特點是什麼?

Spark是一個基於記憶體的,用於大規模資料處理(離線計算、實時計算、快速查詢(互動式查詢))的統一分析引擎。

它內部的組成模組,包含SparkCore,SparkSQL,Spark Streaming,SparkMLlib,SparkGraghx等。

Spark的主要特點包括:

  • 快:Spark計算速度是MapReduce計算速度的10-100倍,Spark使用記憶體計算技術,以及基於彈性分散式資料集(RDD)的計算模型,可以在記憶體中對資料進行高效處理,從而比傳統的基於磁碟的計算系統更快速。

  • 容錯性:Spark可以在節點故障時重新計算丟失的資料,從而避免了資料丟失的問題,保證了任務的可靠性。

  • 多語言支援:Spark提供了多種程式語言API,包括Java、Scala、Python和R等,使得開發者可以使用自己熟悉的語言進行資料處理任務。

  • 資料處理能力:Spark可以處理各種型別的資料,包括結構化資料、半結構化資料和非結構化資料等,並且支援各種資料來源的讀寫操作,如HDFS、Hive、MySQL等。

  • 可擴充套件性:Spark可以在大規模叢集上執行,支援自動分割槽和並行化處理,從而可以處理PB級別的資料。

總的來說,Spark具有高效的效能、容錯性、多語言支援、強大的資料處理能力和良好的可擴充套件性,適用於各種大規模資料處理任務,如機器學習、影像處理、資料探勘、日誌分析等。

2Spark有幾種部署方式,請分別簡要論述?

Spark有三種常見的部署方式,分別是本地模式、單例模式和Yarn模式。

1) Local:執行在一臺機器上,通常是練手或者測試環境。

2)Standalone:構建一個基於Mster+Slaves的資源排程叢集,Spark任務提交給Master執行。是Spark自身的一個排程系統。

3)Yarn: Spark客戶端直接連線Yarn,不需要額外構建Spark叢集。有yarn-client和yarn-cluster兩種模式,主要區別在於:Driver程式的執行節點。

3Spark提交作業的引數

因為我們Spark任務是採用的Shell指令碼進行提交,所以一定會涉及到幾個重要的引數,而這個也是在面試的時候容易被考察到的“細節”。

executor-cores —— 每個executor使用的核心數,預設為1,官方建議2-5個,我們企業是4個
num-executors —— 啟動executors的數量,預設為2
executor-memory —— executor記憶體大小,預設1G
driver-cores —— driver使用核心數,預設為1
driver-memory —— driver記憶體大小,預設512M
在使用Spark提交作業時,可以使用以下引數:

--class:指定要執行的主類名。
--master:指定要連線的Spark叢集的URL。例如,--master yarn將連線到YARN叢集。
--deploy-mode:指定作業的部署模式,可選值為client或cluster。client模式是在客戶端啟動Driver程式,cluster模式則是在叢集中啟動Driver程式。
--executor-memory:指定每個Executor可用的記憶體量。例如,--executor-memory 4g將為每個Executor分配4GB記憶體。
--num-executors:指定要啟動的Executor數量。例如,--num-executors 10將啟動10個Executor。
--executor-cores:指定每個Executor可用的CPU核心數量。例如,--executor-cores 2將為每個Executor分配2個CPU核心。
--conf:用於設定Spark配置屬性。例如,--conf spark.shuffle.compress=true將啟用Shuffle壓縮。
--jars:用於指定需要在作業中使用的JAR檔案。例如,--jars /path/to/jar1,/path/to/jar2將載入jar1和jar2。
--files:用於指定需要在作業中使用的檔案。例如,--files /path/to/file1,/path/to/file2將載入file1和file2。

更多引數和說明可以透過執行spark-submit --help來檢視。

4簡述Spark的作業提交流程

Spark的任務提交方式實際上有兩種,分別是YarnClient模式和YarnCluster模式。大家在回答這個問題的時候,也需要分類去介紹。千萬不要被冗長的步驟嚇到,一定要學會總結差異,發現規律,透過圖形去增強記憶。

YarnClient  執行模式介紹

Spark 經典面試題彙總《一》

YarnCluster 模式介紹

Spark 經典面試題彙總《一》

Spark作業的提交流程如下:

  • 編寫應用程式:首先需要編寫Spark應用程式。這通常是一個基於Spark API的Scala、Java或Python指令碼,它定義了資料處理的流程和邏輯。

  • 打包應用程式:使用構建工具(如sbt、Maven或Gradle)將應用程式打包成JAR檔案。

  • 準備環境:確保叢集中的所有節點都安裝了相同版本的Spark,並且應用程式所需的所有依賴項都已安裝。

  • 啟動Spark叢集:在叢集的一個節點上啟動Spark Master,然後啟動一些Spark Worker程式。

  • 提交作業:使用spark-submit命令提交應用程式,命令包括應用程式的JAR檔案和一些引數,例如作業名稱、Master節點URL、作業配置等。

  • 分配資源:Spark提交器將根據作業配置、叢集資源可用性和其他因素,將作業分配給可用的Worker節點,併為每個Executor分配資源。

  • 執行任務:一旦資源分配完成,Spark將啟動Driver程式,並將作業的任務傳送給Worker節點上的Executor進行執行。

  • 監控進度:Spark Web UI提供了有關作業進度和效能的實時監控資訊,可以用於診斷問題或調整配置。

  • 收集結果:一旦作業完成,Spark會將結果收集並返回給Driver程式。在驅動程式中,可以將結果儲存到外部儲存系統或進行進一步處理。

總之,Spark作業提交流程是一個複雜的過程,需要綜合考慮應用程式、叢集配置和資源分配等多個因素。熟練掌握Spark作業提交流程是成為一名優秀Spark開發人員的關鍵。

5你是如何理解Spark中血統(RDD)的概念?它的作用是什麼?

  • 概念

RDD是彈性分散式資料集,是Spark中最基本的資料抽象,代表一個不可變、可分割槽、裡面的元素可平行計算 的集合。

  • 作用

提供了一個抽象的資料模型,將具體的應用邏輯表達為一系列轉換操作(函式)。另外不同RDD之間的轉換操作之間還可以形成依賴關係,進而實現管道化,從而避免了中間結果的儲存,大大降低了資料複製、磁碟IO和序列化開銷,並且還提供了更多的API(map/reduec/filter/groupBy...)

  • 特點
    • 容錯性:RDD具有容錯性,因為它會自動將資料劃分成多個分割槽,並在叢集中的多個節點上進行復制,從而實現資料的高可靠性和容錯性。

    • 資料共享:RDD允許多個並行操作共享相同的資料集合,以便在不同的計算步驟中複用資料,從而避免了重複的IO操作,提高了計算效率。

    • 最佳化計算:RDD透過支援多個轉換操作和行動操作,允許進行復雜的計算和資料分析,同時也支援對計算過程進行最佳化,以便最大限度地減少計算成本。

    • 血統跟蹤:RDD透過記錄其前一個RDD的依賴關係,構建了一個有向無環圖(DAG)來跟蹤其資料處理流程,從而允許Spark在節點故障時重新計算丟失的分割槽,實現了彈性計算。

    • 血統是指RDD之間的依賴關係,這種依賴關係可以透過DAG(有向無環圖)來表示。每個RDD都會記錄其父RDD的引用和產生該RDD的轉換操作,這樣,如果某個RDD的分割槽丟失或出現故障,Spark可以根據血統資訊重新計算該RDD的丟失分割槽,實現了彈性計算。因此,RDD的血統跟蹤是Spark實現容錯性的重要機制。

6簡述Spark的寬窄依賴,以及Spark如何劃分stage,每個stage又根據什麼決定task個數?

spark的寬窄依賴問題是SparkCore部分的重點考察內容,多數出現在筆試中,大家需要注意。

窄依賴:父RDD的一個分割槽只會被子RDD的一個分割槽依賴

寬依賴:父RDD的一個分割槽會被子RDD的多個分割槽依賴(涉及到shuffle)

那Stage是如何劃分的呢?

  • 根據RDD之間的依賴關係的不同將Job劃分成不同的Stage,遇到一個寬依賴則劃分一個Stage。

  • 每個stage又根據什麼決定task個數?

  • Stage是一個TaskSet,將Stage根據分割槽數劃分成一個個的Task。

  • 這裡為了方便大家理解,貼上一張過程圖

Spark 經典面試題彙總《一》

Spark中的寬依賴和窄依賴是指RDD之間的依賴關係型別。在Spark中,每個RDD都有一個或多個父RDD和一個或多個子RDD,RDD之間的依賴關係分為寬依賴和窄依賴兩種型別:

  • 窄依賴(Narrow Dependency):指一個RDD的每個分割槽只依賴於父RDD的一個或多個分割槽,父RDD的每個分割槽最多隻被一個子RDD的分割槽使用。窄依賴的特點是資料區域性性高,可以在同一個節點上完成計算,從而提高計算效率。

  • 寬依賴(Wide Dependency):指一個RDD的一個或多個分割槽依賴於父RDD的多個分割槽,或者父RDD的同一個分割槽被多個子RDD的分割槽使用。寬依賴的特點是資料區域性性較低,需要進行資料的洗牌操作(Shuffle),從而增加了計算成本和網路傳輸開銷。

在Spark中,每個寬依賴和窄依賴之間的轉換都會形成一個Stage,每個Stage包含一組具有相同依賴關係的Task。一個Stage中的Task個數由多個因素決定,包括可用的CPU核心數、可用記憶體大小、資料分割槽數等。具體來說,Spark會將RDD劃分成多個分割槽,並在每個分割槽上執行一個Task,以便實現平行計算。Task的個數通常等於RDD的分割槽數,這樣可以確保所有Task都具有相同的計算量,並且可以在不同的節點上並行執行。

在Spark中,Stage劃分的基本原則是:如果兩個RDD之間存在寬依賴,那麼它們就屬於不同的Stage。這是因為寬依賴需要進行Shuffle操作,需要將資料從多個節點收集到一個節點上進行計算,這會產生較大的網路開銷和計算成本。因此,將寬依賴放在不同的Stage中可以提高計算效率。而對於窄依賴,Spark會盡量將它們放在同一個Stage中,以便在同一個節點上執行計算,從而提高計算效率。

7列舉Spark常用的transformation和action運算元,有哪些運算元會導致Shuffle?

  • Spark中常用的transformation運算元有:

map:對RDD中的每個元素應用一個函式,返回一個新的RDD。

filter:對RDD中的每個元素應用一個謂詞函式,返回一個包含滿足謂詞的元素的新RDD。

flatMap:類似於map,但是每個輸入元素可以對映到多個輸出元素,返回一個新的RDD。

groupByKey:將具有相同key的元素進行分組,返回一個(key, values)的Tuple,其中values是一個迭代器。

reduceByKey:將具有相同key的元素進行分組,並將每個key對應的values應用一個reduce函式,返回一個(key, reduced value)的Tuple。

join:對兩個具有相同key的RDD進行join操作,返回一個新的RDD。

  • 常用的action運算元有:

count:返回RDD中元素的個數。

collect:將RDD中的所有元素收集到Driver節點上,並返回一個陣列。

first:返回RDD中的第一個元素。

take:返回RDD中前n個元素。

reduce:對RDD中的元素應用一個reduce函式,返回一個單個值。

  • 上述運算元中,groupByKey、reduceByKey、join等運算元會導致Shuffle操作,因為它們需要將具有相同key的元素進行分組,而這些元素通常分佈在不同的節點上。Shuffle操作會將資料從不同的節點收集到一個節點上進行計算,因此需要消耗大量的網路和計算資源。

join()和cogroup():這兩個運算元需要將具有相同鍵的元素進行連線操作,也需要進行Shuffle操作。

sortByKey():這個運算元需要對RDD中的元素進行排序,因此需要進行Shuffle操作。

repartition()和coalesce():這兩個運算元都需要對RDD進行重新分割槽操作,需要進行Shuffle操作。

8reduceByKey與groupByKey的區別,哪一種更具優勢?

  • reduceByKey:按照key進行聚合,在shuffle之前有combine(預聚合)操作,返回結果是RDD[k,v]。

  • groupByKey:按照key進行分組,直接進行shuffle

所以,在實際開發過程中,reduceByKey比groupByKey,更建議使用。但是需要注意是否會影響業務邏輯。

9Repartition和Coalesce 的關係與區別,能簡單說說嗎?

1)關係:

兩者都是用來改變RDD的partition數量的,repartition底層呼叫的就是coalesce方法:coalesce(numPartitions, shuffle = true)

2)區別:

repartition一定會發生shuffle,coalesce 根據傳入的引數來判斷是否發生shuffle。

一般情況下增大rdd的partition數量使用repartition,減少partition數量時使用coalesce。

10簡述下Spark中的快取(cache和persist)與checkpoint機制,並指出兩者的區別和聯絡

  • 關於Spark快取和檢查點的區別,大致可以從這3個角度去回答:

位置

  • Persist 和 Cache將資料儲存在記憶體,Checkpoint將資料儲存在HDFS

生命週期

  • Persist 和 Cache  程式結束後會被清除或手動呼叫unpersist方法,Checkpoint永久儲存不會被刪除。

RDD依賴關係

  • Persist 和 Cache,不會丟掉RDD間的依賴鏈/依賴關係,CheckPoint會斬斷依賴鏈。

11簡述Spark中共享變數(廣播變數和累加器)的基本原理與用途

關於Spark中的廣播變數和累加器的基本原理和用途,

  • 累加器(accumulator)是Spark中提供的一種分散式的變數機制,其原理類似於mapreduce,即分散式的改變,然後聚合這些改變。累加器的一個常見用途是在除錯時對作業執行過程中的事件進行計數。

  • 廣播變數是在每個機器上快取一份,不可變,只讀的,相同的變數,該節點每個任務都能訪問,起到節省資源和最佳化的作用。它通常用來高效分發較大的物件。

12當Spark涉及到資料庫的操作時,如何減少Spark執行中的資料庫連線數?

嗯,有點“調優”的味道,感覺真正的“風暴”即將到來,這道題還是很好回答的,我們只需要減少連線資料庫的次數即可。

  • 使用foreachPartition代替foreach,在foreachPartition內獲取資料庫的連線。

13能介紹下你所知道和使用過的Spark調優嗎?

  • 資源引數調優
num-executors:設定Spark作業總共要用多少個Executor程式來執行

executor-memory:設定每個Executor程式的記憶體

executor-cores:設定每個Executor程式的CPU core數量

driver-memory:設定Driver程式的記憶體

spark.default.parallelism:設定每個stage的預設task數量

  • 開發調優

避免建立重複的RDD

儘可能複用同一個RDD

對多次使用的RDD進行持久化

儘量避免使用shuffle類運算元

使用map-side預聚合的shuffle操作

使用高效能的運算元

①使用reduceByKey/aggregateByKey替代groupByKey

②使用mapPartitions替代普通map 

③使用foreachPartitions替代foreach 

④使用filter之後進行coalesce操作

⑤使用repartitionAndSortWithinPartitions替代repartition與sort類操作
  • 廣播大變數

    • 在運算元函式中使用到外部變數時,預設情況下,Spark會將該變數複製多個副本,透過網路傳輸到task中,此時每個task都有一個變數副本。如果變數本身比較大的話(比如100M,甚至1G),那麼大量的變數副本在網路中傳輸的效能開銷,以及在各個節點的Executor中佔用過多記憶體導致的頻繁GC(垃圾回收),都會極大地影響效能。
  • 使用Kryo最佳化序列化效能

  • 最佳化資料結構

在可能以及合適的情況下,使用佔用記憶體較少的資料結構,但是前提是要保證程式碼的可維護性。

14如何使用Spark實現TopN的獲取(描述思路或使用虛擬碼)?

使用Spark實現TopN的一般思路是先使用MapReduce或者Spark計算出各個資料的得分(或者其他排序依據),然後再對這些得分進行排序,最後取出前N個得分最高的資料。其中,排序的過程是需要進行全域性操作的,會產生Shuffle操作,因此在效能上需要考慮。

以下是一種使用Spark進行TopN操作的虛擬碼:

  • 讀取資料並將資料轉換為RDD格式 rdd = sc.textFile("path/to/data").map(parse_data)

  • 計算每個資料的得分 scores_rdd = rdd.map(lambda data: (data, compute_score(data)))

  • 對得分進行排序 sorted_scores_rdd = scores_rdd.sortBy(lambda score: score[1], ascending=False)

  • 取出前N個得分最高的資料 topN_rdd = sorted_scores_rdd.take(N)

其中,parse_data函式用於將原始資料解析成程式中需要的格式,compute_score函式用於計算資料的得分。在第二步和第三步中,需要根據實際情況選擇合適的運算元,如map()、reduceByKey()、sortBy()等。

來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/70024924/viewspace-2937152/,如需轉載,請註明出處,否則將追究法律責任。

相關文章