zoukankan      html  css  js  c++  java
  • 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);

     

  • 相关阅读:
    OkHttp3Stack volley
    Badge分析
    Android Icon数字角标(BadgeNumber)的实现方式
    Android ORMLite 框架的入门用法
    实现FlowLayout 自动排序标签
    iptables端口转发配置[Ubuntu]
    编译csipsimple的native部分
    开发JavaScript组件
    jQuery组件开发
    Groovy小结:java调用Groovy方法并传递参数
  • 原文地址:https://www.cnblogs.com/si-137/p/13377332.html
Copyright © 2011-2022 走看看