Spark面試題

大資料技術派發表於2021-10-26

1、spark的有幾種部署模式,每種模式特點?(☆☆☆☆☆)

1)本地模式
  Spark不一定非要跑在hadoop叢集,可以在本地,起多個執行緒的方式來指定。將Spark應用以多執行緒的方式直接執行在本地,一般都是為了方便除錯,本地模式分三類
  local:只啟動一個executor
  local[k]:啟動k個executor
  local[*]:啟動跟cpu數目相同的 executor
2)standalone模式
  分散式部署叢集,自帶完整的服務,資源管理和任務監控是Spark自己監控,這個模式也是其他模式的基礎。
3)Spark on yarn模式
  分散式部署叢集,資源和任務監控交給yarn管理,但是目前僅支援粗粒度資源分配方式,包含cluster和client執行模式,cluster適合生產,driver執行在叢集子節點,具有容錯功能,client適合除錯,dirver執行在客戶端。
4)Spark On Mesos模式。
  官方推薦這種模式(當然,原因之一是血緣關係)。正是由於Spark開發之初就考慮到支援Mesos,因此,目前而言,Spark執行在Mesos上會比執行在YARN上更加靈活,更加自然。使用者可選擇兩種排程模式之一執行自己的應用程式:
  (1)粗粒度模式(Coarse-grained Mode):每個應用程式的執行環境由一個Dirver和若干個Executor組成,其中,每個Executor佔用若干資源,內部可執行多個Task(對應多少個“slot”)。應用程式的各個任務正式執行之前,需要將執行環境中的資源全部申請好,且執行過程中要一直佔用這些資源,即使不用,最後程式執行結束後,回收這些資源。
  (2)細粒度模式(Fine-grained Mode):鑑於粗粒度模式會造成大量資源浪費,Spark On Mesos還提供了另外一種排程模式:細粒度模式,這種模式類似於現在的雲端計算,思想是按需分配。

2、Spark為什麼比mapreduce快?(☆☆☆☆☆)

  1)基於記憶體計算,減少低效的磁碟互動;
  2)高效的排程演算法,基於DAG;
  3)容錯機制Linage,精華部分就是DAG和Lingae

3、簡單說一下hadoop和spark的shuffle相同和差異?(☆☆☆☆☆)

  1)從 high-level 的角度來看,兩者並沒有大的差別。 都是將 mapper(Spark 裡是 ShuffleMapTask)的輸出進行 partition,不同的 partition 送到不同的 reducer(Spark 裡 reducer 可能是下一個 stage 裡的 ShuffleMapTask,也可能是 ResultTask)。Reducer 以記憶體作緩衝區,邊 shuffle 邊 aggregate 資料,等到資料 aggregate 好以後進行 reduce() (Spark 裡可能是後續的一系列操作)。
  2)從 low-level 的角度來看,兩者差別不小。 Hadoop MapReduce 是 sort-based,進入 combine() 和 reduce() 的 records 必須先 sort。這樣的好處在於 combine/reduce() 可以處理大規模的資料,因為其輸入資料可以通過外排得到(mapper 對每段資料先做排序,reducer 的 shuffle 對排好序的每段資料做歸併)。目前的 Spark 預設選擇的是 hash-based,通常使用 HashMap 來對 shuffle 來的資料進行 aggregate,不會對資料進行提前排序。如果使用者需要經過排序的資料,那麼需要自己呼叫類似 sortByKey() 的操作;如果你是Spark 1.1的使用者,可以將spark.shuffle.manager設定為sort,則會對資料進行排序。在Spark 1.2中,sort將作為預設的Shuffle實現。
  3)從實現角度來看,兩者也有不少差別。 Hadoop MapReduce 將處理流程劃分出明顯的幾個階段:map(), spill, merge, shuffle, sort, reduce() 等。每個階段各司其職,可以按照過程式的程式設計思想來逐一實現每個階段的功能。在 Spark 中,沒有這樣功能明確的階段,只有不同的 stage 和一系列的 transformation(),所以 spill, merge, aggregate 等操作需要蘊含在 transformation() 中。
  如果我們將 map 端劃分資料、持久化資料的過程稱為 shuffle write,而將 reducer 讀入資料、aggregate 資料的過程稱為 shuffle read。那麼在 Spark 中,問題就變為怎麼在 job 的邏輯或者物理執行圖中加入 shuffle write 和 shuffle read的處理邏輯?以及兩個處理邏輯應該怎麼高效實現?
  Shuffle write由於不要求資料有序,shuffle write 的任務很簡單:將資料 partition 好,並持久化。之所以要持久化,一方面是要減少記憶體儲存空間壓力,另一方面也是為了 fault-tolerance。

4、spark工作機制?(☆☆☆☆☆)

① 構建Application的執行環境,Driver建立一個SparkContext

SparkContext

② SparkContext向資源管理器(Standalone、Mesos、Yarn)申請Executor資源,資源管理器啟動StandaloneExecutorbackend(Executor)
③ Executor向SparkContext申請Task
④ SparkContext將應用程式分發給Executor
⑤ SparkContext就建成DAG圖,DAGScheduler將DAG圖解析成Stage,每個Stage有多個task,形成taskset傳送給task Scheduler,由task Scheduler將Task傳送給Executor執行
⑥ Task在Executor上執行,執行完釋放所有資源

5、spark的優化怎麼做? (☆☆☆☆☆)

  spark調優比較複雜,但是大體可以分為三個方面來進行
  1)平臺層面的調優:防止不必要的jar包分發,提高資料的本地性,選擇高效的儲存格式如parquet
  2)應用程式層面的調優:過濾操作符的優化降低過多小任務,降低單條記錄的資源開銷,處理資料傾斜,複用RDD進行快取,作業並行化執行等等
  3)JVM層面的調優:設定合適的資源量,設定合理的JVM,啟用高效的序列化方法如kyro,增大off head記憶體等等

6、資料本地性是在哪個環節確定的?(☆☆☆☆☆)

  具體的task執行在那他機器上,dag劃分stage的時候確定的

7、RDD的彈性表現在哪幾點?(☆☆☆☆☆)

  1)自動的進行記憶體和磁碟的儲存切換;
  2)基於Lineage的高效容錯;
  3)task如果失敗會自動進行特定次數的重試;
  4)stage如果失敗會自動進行特定次數的重試,而且只會計算失敗的分片;
  5)checkpoint和persist,資料計算之後持久化快取;
  6)資料排程彈性,DAG TASK排程和資源無關;
  7)資料分片的高度彈性。

8、RDD有哪些缺陷?(☆☆☆☆☆)

  1)不支援細粒度的寫和更新操作(如網路爬蟲),spark寫資料是粗粒度的。所謂粗粒度,就是批量寫入資料,為了提高效率。但是讀資料是細粒度的也就是說可以一條條的讀。
  2)不支援增量迭代計算,Flink支援

9、Spark的shuffle過程?(☆☆☆☆☆)

  從下面三點去展開
  1)shuffle過程的劃分
  2)shuffle的中間結果如何儲存
  3)shuffle的資料如何拉取過來
  可以參考這篇博文:http://www.cnblogs.com/jxhd1/p/6528540.html

10、 Spark的資料本地性有哪幾種?(☆☆☆☆☆)

  Spark中的資料本地性有三種:
  1)PROCESS_LOCAL是指讀取快取在本地節點的資料
  2)NODE_LOCAL是指讀取本地節點硬碟資料
  3)ANY是指讀取非本地節點資料
  通常讀取資料PROCESS_LOCAL>NODE_LOCAL>ANY,儘量使資料以PROCESS_LOCAL或NODE_LOCAL方式讀取。其中PROCESS_LOCAL還和cache有關,如果RDD經常用的話將該RDD cache到記憶體中,注意,由於cache是lazy的,所以必須通過一個action的觸發,才能真正的將該RDD cache到記憶體中。

11、Spark為什麼要持久化,一般什麼場景下要進行persist操作?(☆☆☆)

  為什麼要進行持久化?
  spark所有複雜一點的演算法都會有persist身影,spark預設資料放在記憶體,spark很多內容都是放在記憶體的,非常適合高速迭代,1000個步驟只有第一個輸入資料,中間不產生臨時資料,但分散式系統風險很高,所以容易出錯,就要容錯,rdd出錯或者分片可以根據血統算出來,如果沒有對父rdd進行persist 或者cache的化,就需要重頭做。
  以下場景會使用persist
  1)某個步驟計算非常耗時,需要進行persist持久化
  2)計算鏈條非常長,重新恢復要算很多步驟,很好使,persist
  3)checkpoint所在的rdd要持久化persist。checkpoint前,要持久化,寫個rdd.cache或者rdd.persist,將結果儲存起來,再寫checkpoint操作,這樣執行起來會非常快,不需要重新計算rdd鏈條了。checkpoint之前一定會進行persist。
  4)shuffle之後要persist,shuffle要進性網路傳輸,風險很大,資料丟失重來,恢復代價很大
  5)shuffle之前進行persist,框架預設將資料持久化到磁碟,這個是框架自動做的。

12、介紹一下join操作優化經驗?(☆☆☆☆☆)

  join其實常見的就分為兩類: map-side join 和 reduce-side join。當大表和小表join時,用map-side join能顯著提高效率。將多份資料進行關聯是資料處理過程中非常普遍的用法,不過在分散式計算系統中,這個問題往往會變的非常麻煩,因為框架提供的 join 操作一般會將所有資料根據 key 傳送到所有的 reduce 分割槽中去,也就是 shuffle 的過程。造成大量的網路以及磁碟IO消耗,執行效率極其低下,這個過程一般被稱為 reduce-side-join。如果其中有張表較小的話,我們則可以自己實現在 map 端實現資料關聯,跳過大量資料進行 shuffle 的過程,執行時間得到大量縮短,根據不同資料可能會有幾倍到數十倍的效能提升。
  備註:這個題目面試中非常非常大概率見到,務必搜尋相關資料掌握,這裡拋磚引玉。

13、描述Yarn執行一個任務的過程?(☆☆☆☆☆)

YARN任務執行過程

  1)客戶端client向ResouceManager提交Application,ResouceManager接受Application並根據叢集資源狀況選取一個node來啟動Application的任務排程器driver(ApplicationMaster)。
  2)ResouceManager找到那個node,命令其該node上的nodeManager來啟動一個新的 JVM程式執行程式的driver(ApplicationMaster)部分,driver(ApplicationMaster)啟動時會首先向ResourceManager註冊,說明由自己來負責當前程式的執行。
  3)driver(ApplicationMaster)開始下載相關jar包等各種資源,基於下載的jar等資訊決定向ResourceManager申請具體的資源內容。
  4)ResouceManager接受到driver(ApplicationMaster)提出的申請後,會最大化的滿足 資源分配請求,併傳送資源的後設資料資訊給driver(ApplicationMaster)。
  5)driver(ApplicationMaster)收到發過來的資源後設資料資訊後會根據後設資料資訊發指令給具體機器上的NodeManager,讓其啟動具體的container。
  6)NodeManager收到driver發來的指令,啟動container,container啟動後必須向driver(ApplicationMaster)註冊。
  7)driver(ApplicationMaster)收到container的註冊,開始進行任務的排程和計算,直到 任務完成。
  注意:如果ResourceManager第一次沒有能夠滿足driver(ApplicationMaster)的資源請求 ,後續發現有空閒的資源,會主動向driver(ApplicationMaster)傳送可用資源的後設資料資訊以提供更多的資源用於當前程式的執行。

14、Spark on Yarn 模式有哪些優點?(☆☆☆☆☆)

  1)與其他計算框架共享叢集資源(Spark框架與MapReduce框架同時執行,如果不用Yarn進行資源分配,MapReduce分到的記憶體資源會很少,效率低下);資源按需分配,進而提高叢集資源利用等。
  2)相較於Spark自帶的Standalone模式,Yarn的資源分配更加細緻。
  3)Application部署簡化,例如Spark,Storm等多種框架的應用由客戶端提交後,由Yarn負責資源的管理和排程,利用Container作為資源隔離的單位,以它為單位去使用記憶體,cpu等。
  4)Yarn通過佇列的方式,管理同時執行在Yarn叢集中的多個服務,可根據不同型別的應用程式負載情況,調整對應的資源使用量,實現資源彈性管理。

15、談談你對container的理解?(☆☆☆☆☆)

  1)Container作為資源分配和排程的基本單位,其中封裝了的資源如記憶體,CPU,磁碟,網路頻寬等。 目前yarn僅僅封裝記憶體和CPU
  2)Container由ApplicationMaster向ResourceManager申請的,由ResouceManager中的資源排程器非同步分配給ApplicationMaster
  3)Container的執行是由ApplicationMaster向資源所在的NodeManager發起的,Container執行時需提供內部執行的任務命令

16、Spark使用parquet檔案儲存格式能帶來哪些好處?(☆☆☆☆☆)

  1)如果說HDFS是大資料時代分散式檔案系統首選標準,那麼parquet則是整個大資料時代檔案儲存格式實時首選標準。
  2)速度更快:從使用spark sql操作普通檔案CSV和parquet檔案速度對比上看,絕大多數情況會比使用csv等普通檔案速度提升10倍左右,在一些普通檔案系統無法在spark上成功執行的情況下,使用parquet很多時候可以成功執行。
  3)parquet的壓縮技術非常穩定出色,在spark sql中對壓縮技術的處理可能無法正常的完成工作(例如會導致lost task,lost executor)但是此時如果使用parquet就可以正常的完成。
  4)極大的減少磁碟I/o,通常情況下能夠減少75%的儲存空間,由此可以極大的減少spark sql處理資料的時候的資料輸入內容,尤其是在spark1.6x中有個下推過濾器在一些情況下可以極大的減少磁碟的IO和記憶體的佔用,(下推過濾器)。
  5)spark 1.6x parquet方式極大的提升了掃描的吞吐量,極大提高了資料的查詢速度spark1.6和spark1.5x相比而言,提升了大約1倍的速度,在spark1.6X中,操作parquet時候cpu也進行了極大的優化,有效的降低了cpu消耗。
  6)採用parquet可以極大的優化spark的排程和執行。我們測試spark如果用parquet可以有效的減少stage的執行消耗,同時可以優化執行路徑。

17、介紹parition和block有什麼關聯關係?(☆☆☆☆☆)

  1)hdfs中的block是分散式儲存的最小單元,等分,可設定冗餘,這樣設計有一部分磁碟空間的浪費,但是整齊的block大小,便於快速找到、讀取對應的內容;
  2)Spark中的partion是彈性分散式資料集RDD的最小單元,RDD是由分佈在各個節點上的partion組成的。partion是指的spark在計算過程中,生成的資料在計算空間內最小單元,同一份資料(RDD)的partion大小不一,數量不定,是根據application裡的運算元和最初讀入的資料分塊數量決定;
  3)block位於儲存空間、partion位於計算空間,block的大小是固定的、partion大小是不固定的,是從2個不同的角度去看資料。

18、Spark應用程式的執行過程是什麼?(☆☆☆☆☆)

  1)構建Spark Application的執行環境(啟動SparkContext),SparkContext向資源管理器(可以是Standalone、Mesos或YARN)註冊並申請執行Executor資源;
  2)資源管理器分配Executor資源並啟動StandaloneExecutorBackend,Executor執行情況將隨著心跳傳送到資源管理器上;
  3)SparkContext構建成DAG圖,將DAG圖分解成Stage,並把Taskset傳送給Task Scheduler。Executor向SparkContext申請Task,Task Scheduler將Task發放給Executor執行同時SparkContext將應用程式程式碼發放給Executor;
  4)Task在Executor上執行,執行完畢釋放所有資源。

19、不需要排序的hash shuffle是否一定比需要排序的sort shuffle速度快?(☆☆☆☆☆)

  不一定,當資料規模小,Hash shuffle快於Sorted Shuffle資料規模大的時候;當資料量大,sorted Shuffle會比Hash shuffle快很多,因為數量大的有很多小檔案,不均勻,甚至出現資料傾斜,消耗記憶體大,1.x之前spark使用hash,適合處理中小規模,1.x之後,增加了Sorted shuffle,Spark更能勝任大規模處理了。

20、Sort-based shuffle的缺陷? (☆☆☆☆☆)

  1)如果mapper中task的數量過大,依舊會產生很多小檔案,此時在shuffle傳遞資料的過程中reducer段,reduce會需要同時大量的記錄進行反序列化,導致大量的記憶體消耗和GC的巨大負擔,造成系統緩慢甚至崩潰。
  2)如果需要在分片內也進行排序,此時需要進行mapper段和reducer段的兩次排序。

21、spark.storage.memoryFraction引數的含義,實際生產中如何調優?(☆☆☆☆☆)

  1)用於設定RDD持久化資料在Executor記憶體中能佔的比例,預設是0.6,,預設Executor 60%的記憶體,可以用來儲存持久化的RDD資料。根據你選擇的不同的持久化策略,如果記憶體不夠時,可能資料就不會持久化,或者資料會寫入磁碟;
  2)如果持久化操作比較多,可以提高spark.storage.memoryFraction引數,使得更多的持久化資料儲存在記憶體中,提高資料的讀取效能,如果shuffle的操作比較多,有很多的資料讀寫操作到JVM中,那麼應該調小一點,節約出更多的記憶體給JVM,避免過多的JVM gc發生。在web ui中觀察如果發現gc時間很長,可以設定spark.storage.memoryFraction更小一點。

22、介紹一下你對Unified Memory Management記憶體管理模型的理解?(☆☆☆☆☆)

  Spark中的記憶體使用分為兩部分:執行(execution)與儲存(storage)。執行記憶體主要用於shuffles、joins、sorts和aggregations,儲存記憶體則用於快取或者跨節點的內部資料傳輸。1.6之前,對於一個Executor,記憶體都由以下部分構成:
  1)ExecutionMemory。這片記憶體區域是為了解決 shuffles,joins, sorts and aggregations 過程中為了避免頻繁IO需要的buffer。 通過spark.shuffle.memoryFraction(預設 0.2) 配置。
  2)StorageMemory。這片記憶體區域是為了解決 block cache(就是你顯示呼叫rdd.cache, rdd.persist等方法), 還有就是broadcasts,以及task results的儲存。可以通過引數 spark.storage.memoryFraction(預設0.6)設定。
  3)OtherMemory。給系統預留的,因為程式本身執行也是需要記憶體的(預設為0.2)。
  傳統記憶體管理的不足:
  1)Shuffle佔用記憶體0.2*0.8,記憶體分配這麼少,可能會將資料spill到磁碟,頻繁的磁碟IO是很大的負擔,Storage記憶體佔用0.6,主要是為了迭代處理。傳統的Spark記憶體分配對操作人的要求非常高。(Shuffle分配記憶體:ShuffleMemoryManager, TaskMemoryManager, ExecutorMemoryManager)一個Task獲得全部的Execution的Memory,其他Task過來就沒有記憶體了,只能等待;
  2)預設情況下,Task線上程中可能會佔滿整個記憶體,分片資料

相關文章