spark面試總結3


Spark core面試篇03
1.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的執行消耗,同時可以優化執行路徑
    2.Executor之間如何共享數據?
    答:基於hdfs或者基於tachyon
    3.Spark累加器有哪些特點?
    1)累加器在全局唯一的,只增不減,記錄全局集群的唯一狀態
    2)在exe中修改它,在driver讀取
    3)executor級別共享的,廣播變量是task級別的共享
    兩個application不可以共享累加器,但是同一個app不同的job可以共享
    4.如何在一個不確定的數據規模的范圍內進行排序?
    為了提高效率,要划分划分,划分的范圍並且是有序的
    要么有序,要么降序?
    水塘抽樣:目的是從一個集合中選取,集合非常答,適合內存
    無法容納數據的時候使用
    從N中抽取出K個,N是隨機數
    5.spark hashParitioner的弊端是什么?
    答:HashPartitioner分區的原理很簡單,對於給定的key,計算其hashCode,並除於分區的個數取余,如果余數小於0,則用余數+分區的個數,最后返回的值就是這個key所屬的分區ID;弊端是數據不均勻,容易導致數據傾斜,極端情況下某幾個分區會擁有rdd的所有數據
    6.RangePartitioner分區的原理?
    答:RangePartitioner分區則盡量保證每個分區中數據量的均勻,而且分區與分區之間是有序的,也就是說一個分區中的元素肯定都是比另一個分區內的元素小或者大;但是分區內的元素是不能保證順序的。簡單的說就是將一定范圍內的數映射到某一個分區內。其原理是水塘抽樣。可以參考這篇博文
    https://www.iteblog.com/archives/1522.html
    7.介紹parition和block有什么關聯關系?
    答:1)hdfs中的block是分布式存儲的最小單元,等分,可設置冗余,這樣設計有一部分磁盤空間的浪費,但是整齊的block大小,便於快速找到、讀取對應的內容;2)Spark中的partion是彈性分布式數據集RDD的最小單元,RDD是由分布在各個節點上的partion組成的。partion是指的spark在計算過程中,生成的數據在計算空間內最小單元,同一份數據(RDD)的partion大小不一,數量不定,是根據application里的算子和最初讀入的數據分塊數量決定;3)block位於存儲空間、partion位於計算空間,block的大小是固定的、partion大小是不固定的,是從2個不同的角度去看數據。
    8.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上運行,運行完畢釋放所有資源。
    9.hbase預分區個數和spark過程中的reduce個數相同么
    答:和spark的map個數相同,reduce個數如果沒有設置和reduce前的map數相同。
    10.如何理解Standalone模式下,Spark資源分配是粗粒度的?
    答:spark默認情況下資源分配是粗粒度的,也就是說程序在提交時就分配好資源,后面執行的時候
    使用分配好的資源,除非資源出現了故障才會重新分配。比如Spark shell啟動,已提交,一注冊,哪怕沒有任務,worker都會分配資源給executor。
    11.Spark如何自定義partitioner分區器?
    答:1)spark默認實現了HashPartitioner和RangePartitioner兩種分區策略,我們也可以自己擴展分區策略,自定義分區器的時候繼承org.apache.spark.Partitioner類,實現類中的三個方法
    def numPartitions: Int:這個方法需要返回你想要創建分區的個數;
    def getPartition(key: Any): Int:這個函數需要對輸入的key做計算,然后返回該key的分區ID,范圍一定是0到numPartitions-1;
    equals():這個是Java標准的判斷相等的函數,之所以要求用戶實現這個函數是因為Spark內部會比較兩個RDD的分區是否一樣。
    2)使用,調用parttionBy方法中傳入自定義分區對象
    參考:http://blog.csdn.net/high2011/article/details/68491115
    12.spark中task有幾種類型?
    答:2種類型:1)result task類型,最后一個task,2是shuffleMapTask類型,除了最后一個task都是
    13.union操作是產生寬依賴還是窄依賴?
    答:窄依賴
    14.rangePartioner分區器特點?
    答:rangePartioner盡量保證每個分區中數據量的均勻,而且分區與分區之間是有序的,一個分區中的元素肯定都是比另一個分區內的元素小或者大;但是分區內的元素是不能保證順序的。簡單的說就是將一定范圍內的數映射到某一個分區內。RangePartitioner作用:將一定范圍內的數映射到某一個分區內,在實現中,分界的算法尤為重要。算法對應的函數是rangeBounds
    15.什么是二次排序,你是如何用spark實現二次排序的?(互聯網公司常面)
    答:就是考慮2個維度的排序,key相同的情況下如何排序,參考博文:http://blog.csdn.net/sundujing/article/details/51399606
    16.如何使用Spark解決TopN問題?(互聯網公司常面)
    答:常見的面試題,參考博文:http://www.cnblogs.com/yurunmiao/p/4898672.html
    17.如何使用Spark解決分組排序問題?(互聯網公司常面)
    組織數據形式:
    aa 11
    bb 11
    cc 34
    aa 22
    bb 67
    cc 29
    aa 36
    bb 33
    cc 30
    aa 42
    bb 44
    cc 49
    需求:
    1、對上述數據按key值進行分組
    2、對分組后的值進行排序
    3、截取分組后值得top 3位以key-value形式返回結果
    答案:如下

val groupTopNRdd = sc.textFile("hdfs://db02:8020/user/hadoop/groupsorttop/groupsorttop.data")
groupTopNRdd.map(_.split(" ")).map(x => (x(0),x(1))).groupByKey().map(
x => {
val xx = x._1
val yy = x._2
(xx,yy.toList.sorted.reverse.take(3))
}
).collect

18.窄依賴父RDD的partition和子RDD的parition是不是都是一對一的關系?
答:不一定,除了一對一的窄依賴,還包含一對固定個數的窄依賴(就是對父RDD的依賴的Partition的數量不會隨着RDD數量規模的改變而改變),比如join操作的每個partiion僅僅和已知的partition進行join,這個join操作是窄依賴,依賴固定數量的父rdd,因為是確定的partition關系
19.Hadoop中,Mapreduce操作的mapper和reducer階段相當於spark中的哪幾個算子?
答:相當於spark中的map算子和reduceByKey算子,當然還是有點區別的,MR會自動進行排序的,spark要看你用的是什么partitioner
20.什么是shuffle,以及為什么需要shuffle?
shuffle中文翻譯為洗牌,需要shuffle的原因是:某種具有共同特征的數據匯聚到一個計算節點上進行計算
21.不需要排序的hash shuffle是否一定比需要排序的sort shuffle速度快?
答:不一定!!當數據規模小,Hash shuffle快於Sorted Shuffle數據規模大的時候;當數據量大,sorted Shuffle會比Hash shuffle快很多,因為數量大的有很多小文件,不均勻,甚至出現數據傾斜,消耗內存大,1.x之前spark使用hash,適合處理中小規模,1.x之后,增加了Sorted shuffle,Spark更能勝任大規模處理了。
22.Spark中的HashShufle的有哪些不足?
答:1)shuffle產生海量的小文件在磁盤上,此時會產生大量耗時的、低效的IO操作;2).容易導致內存不夠用,由於內存需要保存海量的文件操作句柄和臨時緩存信息,如果數據處理規模比較大的化,容易出現OOM;3)容易出現數據傾斜,導致OOM
23.conslidate是如何優化Hash shuffle時在map端產生的小文件?
答:1)conslidate為了解決Hash Shuffle同時打開過多文件導致Writer handler內存使用過大以及產生過多文件導致大量的隨機讀寫帶來的低效磁盤IO;2)conslidate根據CPU的個數來決定每個task shuffle map端產生多少個文件,假設原來有10個task,100個reduce,每個CPU有10個CPU
那么使用hash shuffle會產生10100=1000個文件,conslidate產生1010=100個文件
備注:conslidate部分減少了文件和文件句柄,並行讀很高的情況下(task很多時)還是會很多文件
24.Sort-basesd shuffle產生多少個臨時文件
答:2*Map階段所有的task數量,Mapper階段中並行的Partition的總數量,其實就是Mapper端task
25.Sort-based shuffle的缺陷?

  1. 如果mapper中task的數量過大,依舊會產生很多小文件,此時在shuffle傳遞數據的過程中reducer段,reduce會需要同時大量的記錄進行反序列化,導致大量的內存消耗和GC的巨大負擔,造成系統緩慢甚至崩潰
    2)如果需要在分片內也進行排序,此時需要進行mapper段和reducer段的兩次排序
    26.Spark shell啟動時會啟動derby?
    答: spark shell啟動會啟動spark sql,spark sql默認使用derby保存元數據,但是盡量不要用derby,它是單實例,不利於開發。會在本地生成一個文件metastore_db,如果啟動報錯,就把那個文件給刪了 ,derby數據庫是單實例,不能支持多個用戶同時操作,盡量避免使用
    27.spark.default.parallelism這個參數有什么意義,實際生產中如何設置?
    答:1)參數用於設置每個stage的默認task數量。這個參數極為重要,如果不設置可能會直接影響你的Spark作業性能;2)很多人都不會設置這個參數,會使得集群非常低效,你的cpu,內存再多,如果task始終為1,那也是浪費,spark官網建議task個數為CPU的核數executor的個數的2~3倍。
    28.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更小一點。
    29.spark.shuffle.memoryFraction參數的含義,以及優化經驗?
    答:1)spark.shuffle.memoryFraction是shuffle調優中 重要參數,shuffle從上一個task拉去數據過來,要在Executor進行聚合操作,聚合操作時使用Executor內存的比例由該參數決定,默認是20%
    如果聚合時數據超過了該大小,那么就會spill到磁盤,極大降低性能;2)如果Spark作業中的RDD持久化操作較少,shuffle操作較多時,建議降低持久化操作的內存占比,提高shuffle操作的內存占比比例,避免shuffle過程中數據過多時內存不夠用,必須溢寫到磁盤上,降低了性能。此外,如果發現作業由於頻繁的gc導致運行緩慢,意味着task執行用戶代碼的內存不夠用,那么同樣建議調低這個參數的值
    30.介紹一下你對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(就是你顯示調用dd.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在線程中可能會占滿整個內存,分片數據特別大的情況下就會出現這種情況,其他Task沒有內存了,剩下的cores就空閑了,這是巨大的浪費。這也是人為操作的不當造成的。
    3).MEMORY_AND_DISK_SER的storage方式,獲得RDD的數據是一條條獲取,iterator的方式。如果內存不夠(spark.storage.unrollFraction),unroll的讀取數據過程,就是看內存是否足夠,如果足夠,就下一條。unroll的space是從Storage的內存空間中獲得的。unroll的方式失敗,就會直接放磁盤。
    4). 默認情況下,Task在spill到磁盤之前,會將部分數據存放到內存上,如果獲取不到內存,就不會執行。永無止境的等待,消耗CPU和內存。
    在此基礎上,Spark提出了UnifiedMemoryManager,不再分ExecutionMemory和Storage Memory,實際上還是分的,只不過是Execution Memory訪問Storage Memory,Storage Memory也可以訪問Execution Memory,如果內存不夠,就會去借。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM