Hadoop(MapReducer)面試題


一、單選題

1、Shuffle中Partitioner 分區發生在哪個過程( A )

A. 溢寫過程

B. 本地Merge

C. reduce函數階段

D. map函數階段

 

2、在整個maprduce運行階段,數據是以(   A     )形式存在的

A. key/value

B. LongWritable

C. Text

D. IntWritable

 

3、下列哪個方法提交job任務的入口方法 (    B       )

A. JoB.addCacheFile()

B. JoB.waitForCompletion()

C. JoB.setMapperClass()

D. JoB.setJarByClass()


 

二、多選題

1、下列哪些是對reduceTask階段任務正確理解(ABC )

A. 對多個mapTask任務輸出key,value,按照不同的分區通過網絡copy到不同的reduceTask節點處理。

B. 對多個mapTask任務的輸出進行合並、排序。再reduce函數中實現自己的邏輯,對輸入的key、value處理,轉換成新的key、value輸出。

C. outputformat把reducer輸出的key,value保存到文件中。

D. reduceTask階段不會根據key進行分組和排序

 

2、執行一個job, 如果這個job的輸出路徑已經存在,那么程序會 ( CD )

A. 覆蓋這個輸出路徑

B. 拋出警告,但是能夠繼續執行

C. 拋出一個異常,然后退出程序的執行

D. 會拋出文件路徑已存在的異常

 

3、對mapreduce數據類型理解正確(AB  )

A. Java中的String類型在Mapreduce中對應的是Text類型

B. hadoop的序列化,對象可以被序列化成二進制字節序列進行網絡傳輸和存儲

C. Mapreduce中的數據類型和java一模一樣

D. Mapreduce中的數據類型完全和java中基本類型是通用的

 

4、下列說法正確的是(ABC )

A. mapreduce總體上分為maptask階段和reducetask階段

B. shfflue階段由maptask的map方法之后的部分和reduce方法之前前部分組成

C. shfflue階段可能會造成數據傾斜

D. shfflue階段不會對數據進行排序和分區

 

5、下列說法正確的是 ( BCD )

A. inputformat階段會對文件進行切片,切片過程是物理上的切片,切切實實的對數據進行了分割

B. mr中默認使用的是TextInputFormat對文件進行讀取,一次讀取一行,偏移量作為key值,行內容作為value值對應的數據類型為LongWritable和Text

C. mapreduce運行過程中切片的數量決定了maptask的數量,maptask任務並行執行互不影響。

D. inputformat會將文件轉換為(key, value)值得形式輸出到mapper類的map()方法中 

 

6、下列描述正確的是(ABC )

A. 默認的reduceTask數量為1意味着所有的mapTask處理后的數據都會交給這個reduceTask進行數據的匯總,最終輸出一個文件

B. 當分區數量大於reduceTask數量時,程序運行出錯

C. 自定義分區首先需要定義一個類,繼承自Partitioner,實現getPartition()方法根據具體需求返回對於的分區號。

D. ReduceTask的數量越多越好,這樣處理數據執行的效率越高


 

三、判斷題

1、如果reduceTask存在多個,那么單個ReduceTask負責從不同MapTask上拷貝同一分區數據最終對數據進行歸並排序和分組,將數據一組一組的傳遞給Reducer類中的reduce方法中進行處理( )

 

2、MapReduce是一個分布式的運算程序編程框架,適合處理大量的離線數據,有良好的擴展性和高容錯性( 對 

 

3、在整個mapreduce階段共實現了2次排序(

 

4、在整個Shufflue過程中環形緩沖區得大小默認為100M,存儲量達到百分之80則完成溢寫,將內存中得數據寫入到磁盤中(

 

5、 使用hadoop-daemon.sh start/stop resourcemanager 命令啟動和停止resourcemanager (   )


 

四、簡答題

 

1、簡單描述Shuffle過程環形緩沖區的作用(shuffle流程概述)?

[答案]key,value從map()方法輸出后,被outputcollector收集通過HashPartitioner類的getpartitioner()方法獲取分區號,進入環形緩沖區。默認情況下,環形緩沖區為100MB。當環形環形緩沖區存儲達到80%,開始執行溢寫過程,溢寫過程中如果有其他數據進入,那么由剩余的20%反向寫入。溢寫過程會根據key,value先根據分區進行排序,再根據key值進行排序,后生成一個溢寫文件(再對應的分區下根據key值有序),maptask將溢寫文件歸並排序后落入本地磁盤,reduceTask階段將多個mapTask下相同分區的數據copy到指定的reduceTask中進行歸並排序、分組后一次讀取一組數據給reduce()函數。      

 

2、mapreduce在哪些階段(位置)實現了排序?默認是怎么排序的?如何自定義排序?

[答案](1)MapTask和ReduceTask均會對數據按照key進行排序。

 MapTask,會將處理的結果暫時放到環形緩沖區中,當環形緩沖區使用率達到一定閾值(100M的百分之80)后,對緩沖區中的數據進行一次快速排序,並將有序數據溢寫到磁盤上,最后會對磁盤上所有文件溢寫文件進行歸並排序。

 ReduceTask,從每個MapTask上拷貝對應分區的數據文件,如果文件大小超過一定閾值,則溢寫磁盤上,否則存儲在內存中。當所有數據拷貝完畢后,ReduceTask統一對內存和磁盤上的所有數據進行一次歸並排序。

(2)排序操作屬於Hadoop的默認行為。任何應用程序中的數據均會被排序,默認排序是按照字典順序排序,實現該排序的方法是快速排序。

(3)我們需要在數據對象類中實現WritableComparable接口中的 compareTo方法(自然比較方法),從而實現對當前對象和傳入對象的比對,實現排序。

 

3、Combiner是什么有什么作用?Combiner的作用位置和Reducer的作用位置有什么不同?

[答案](1)Combiner是MR程序中Mapper和Reducer之外的一種組件,繼承自reducer,是可選的,並不是必須存在的,因為只有在不影響最終業務結果的場景下才能使用。Combiner的作用就是對每一個MapTask的輸出進行局部匯總,以減小網絡傳輸量

  (2)Combiner是在每一個MapTask所在的節點運行;Reducer是接收全局所有Mapper的輸出結果

 

4、hadoop序列化的特點?如何實現序列化?序列化和反序列化時要注意什么?

[答案](1) hadoop序列化之序列化必要數據,所以具有緊湊、快速高效、可擴展、互操作的特點,

(2)必須實現Writable接口,重寫序列化public void write(DataOutput out)方法和反序列化public void readFields(DataInput in)方法

(3)序列化時要注意數據的數據類型,注意反序列化的順序和序列化的順序完全一致

 

5、mapreduce處理數據時FileInputFormat中getSplits()方法是如何對數據進行切片的?

[答案] 默認情況下為了避免mr處理數據的過程中存在網絡數據傳輸,從而降低mr的效率,默認的切片大小為block塊大小(128M),FileInputFormat中getSplits()方法會根據文件大小將文件拆分成splits,如果單個文件較小小於128的1.1倍,則每個文件為一個split,並將文件按行分割形成<key,value>對,如果單個文件較大。超過block塊(128M)默認大小得1.1倍,則會將文件切分為多個split,切片數量決定了maptask的任務數量。

 

6、mr默認的reduceTask數量是多少?mr默認是如何為key,value分配分區的?總結如何自定義分區?使用自定義分區的注意事項(reducetask和分區的關系)?
(1)默認的reduceTask數量為1意味着所有的mapTask處理后的數據都會交給這個reduceTask進行數據的匯總,最終輸出一個文件
(2)數據在經過map方法的context.write()寫出后,會通過outputcollector收集,底層調用HashPartitioner類的getPartition()方法通過(key.hashCode() & Integer.MAX_VALUE) % numReduceTasks模得到的,但是用戶沒法控制哪個key存儲到哪個分區。
(3)自定義分區首先需要定義一個類,繼承自Partitioner,實現getPartition()方法根據具體需求返回對於的分區號,最后通過job.setPartitionerClass()設置分區類

 1 public class FlowPartitioner extends Partitioner<Text,FlowBean> {  2 public int getPartition(Text text, FlowBean flowBean, int numPartitions) {  3 //分區號從0開始:5reducetask 5個分區:0~4  4 //手機號136、137、138、139開頭都分別放到一個獨立的4個文件中,  5 //其他開頭的放到一個文件中。
 6   String phonenum = text.toString();  7   switch (phonenum.substring(0,3)){  8     case "136":  9       return 0; 10     case "137": 11       return 1; 12     case "138": 13       return 2; 14     case "139": 15       return 3; 16     default: 17       return 4; 18     } 19   } 20 }

(4)注意:
分區號從0開始,不要跳號
當分區數量大於reduceTask數量時,程序運行出錯
當設置reduceTask的數量為一時,不走分區方法
當設置的reduceTask數量大於分區時,會產生空的輸出文件

 


7、如何實現根據bean對象中的某一個值進行分組?
此場景我們通常使用的是輔助分組,定義類繼承自WritableComparator,重寫compare()方法通過對象中的某一個或者多個參數比對,參數相同則視為同一組數據進入到reduce方法中。
注意:使用時需要創建一個構造器將比較對象的類傳給父類(不然會報出Null..空指針異常)

8、job提交流程步驟:

 

waitForCompletion 提交job 任務的入口方法
  if(state == JobState.DEFINE)判斷任務是否處於定義狀態
  submit();
    ensureState(JobState.DEFINE); //再次確認任務狀態(不是DEFINE狀態則拋出異常)
    setUseNewAPI();判斷當前是走新的api還是舊的api
    connect(); 實例化cluster (明確mr運行在本地還是yarn)
    submitJobInternal 真正提交任務的方法
      checkSpecs(job);
        checkOutputSpecs:檢查輸出路徑是否存在和有沒有設置
      submitClient.getNewJobID():獲取jobid
      writeSplits:切片分割數據的方法
      writeConf(conf, submitJobFile):將切片信息和配置文件寫入到臨時目錄
      status = submitClient.submitJob(jobId, submitJobDir.toString() 提交job任務,返回提交狀態

    state = JobState.RUNNING提交任務完成后將DEFINE改為RUNNING
    isSuccessful() 判斷任務執行成功還是失敗
      return status.getState() == JobStatus.State.SUCCEEDED;

9、處理數據時怎么完成切片的

 

inpt -> inputFormat -> map ->shuffle -> reduce -> outputformat -> 本地文件
默認私用的是TextInputFormat

  getSplits():切片方法
  isSplitable(job, path):判斷文件是否支持切片,根據文件路徑獲取壓縮格式,如果支持切片返回true,如果文件不是壓縮文件,則直接返回true
  file.getBlockSize();獲取塊大小
  Math.max(minSize, Math.min(maxSize, blockSize)):獲取切片的大小
    當需要讓切片的大小小於塊大小的時,要調整maxsize
    當需要讓切片的大小大於塊大小的時,要調整minsize
    默認的切片大小時128M
  long bytesRemaining = length;
  while (((double) bytesRemaining)/splitSize > SPLIT_SLOP) {
    int blkIndex = getBlockIndex(blkLocations, length-bytesRemaining);
    splits.add(makeSplit(path, length-bytesRemaining, splitSize,
      blkLocations[blkIndex].getHosts(),
      blkLocations[blkIndex].getCachedHosts()));
    bytesRemaining -= splitSize;
  }

10、IntFormat

inputFormat:把文件內容轉換成key,value值
默認使用的是TextInputFormat
InputFormat<?, ?> input =
ReflectionUtils.newInstance(job.getInputFormatClass(), conf);

TextInputFormat extends FileInputFormat<LongWritable, Text>
TextInputFormat:沒有重寫切片方法getSplits,默認使用的時FileInputFormat的切片方法
返回:LineRecordReader -> LongWritable, Text

NLineInputFormat: NLineInputFormat extends FileInputFormat<LongWritable, Text>
NLineInputFormat:重寫了getSplits方法,默認按照行進行切片
返回:LineRecordReader -> LongWritable, Text

CombineFileInputFormat: CombineFileInputFormat<K, V> extends FileInputFormat
CombineTextInputFormat extends CombineFileInputFormat<LongWritable,Text>
CombineFileInputFormat:重寫了getSplits方法,自定義切片的大小
返回的是:CombineFileRecordReader ->LongWritable,Text

KeyValueTextInputFormat:KeyValueTextInputFormat extends FileInputFormat<Text, Text>
KeyValueTextInputFormat:沒有重寫切片方法getSplits,默認使用的時FileInputFormat的切片方法
返回的是:KeyValueLineRecordReader -> Text, Text

SequenceFileInputFormat<K, V> extends FileInputFormat<K, V>
SequenceFileInputFormat:沒有重寫切片方法getSplits,默認使用的時FileInputFormat的切片方法
返回的是:SequenceFileRecordReader -> Text, Text

 11、壓縮

hadoop種的壓縮方式有哪些?哪些方式壓縮文件支持切片?mr可以在哪些位置執行壓縮?
壓縮的作用(優點)和原則是什么?默認是否開啟了壓縮,怎么開啟map、reduce端的壓縮功能?
(1) DEFLATE、Gzip、bzip2(支持切片)、LZO(支持切片)、Snappy
(2) 可以在mapreduce執行任務前(數據輸入前的數據壓縮)、任務中(map到reduce的數據傳輸過程中的數據壓縮)、任務后(執行完畢后的數據壓縮)
(3)壓縮會占用一定的CPU資源,合理采用壓縮可以減少磁盤io和網絡數據傳輸,提高mr的整體運行效率原則:運算密集型任務少用壓縮,IO密集型任務多使用壓縮
(4)mr默認沒有開啟壓縮功能
// 開啟map端輸出壓縮
configuration.setBoolean("mapreduce.map.output.compress", true);
// 設置map端輸出壓縮方式
configuration.setClass("mapreduce.map.output.compress.codec", BZip2Codec.class, CompressionCodec.class);

//設置reduce端輸出壓縮開啟
FileOutputFormat.setCompressOutput(job, true);
// 設置壓縮的方式
FileOutputFormat.setOutputCompressorClass(job, BZip2Codec.class);

 

 

 


免責聲明!

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



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