Hadoop 学习笔记(转)

来源:互联网 发布:淘宝网装修的工作流程 编辑:程序博客网 时间:2024/04/29 05:32
1. Hadoop框架的两个重点:MapReduce 和HDFS
MapReduce:
        (1)在map进行之前,需要对输入文件在客户端先进行“分片”,然后将分片信息上传到HDFS。
        (2)分片上传结束后,jobtracker拿到分片信息,来分配map,reduct task;map对每条记录的输出以<key,value> 的形式输出。
        (3)如果定义了combiner,则在本地会对map处理的结果进行处理:对相同key的聚合,对key的排序,value的迭代。combiner完成类似于本地reduce的功能。
        (4)在进入reduce阶段之前,系统会完成一些列操作(merge,sort):将list中key相同的数据进行合并、排序,最后形成<k1`,list<v1`>> 的数据;
             然后发往一个reduce
        (5)进入一个reduce,相同的key的map输出会到达同一个reduce,reduce对key相同的多个value进行“reduce操作”;
        > 没有combiner的处理过程:
              
        > 添加combiner的处理过程:
              
          

 
         ?为什么我买的map函数和reduce函数一般使用静态类?
           答:task内部可以共享静态类属性,每个task可能会多次调用map或reduce函数,但每个key只对应某个节点上的某个task的reduce函数的一次执行。
            多个task之间不能共享静态类属性,即使是在同一台机器上,因为是以进程的方式在运行。




        1. Map类:(继承TableMapper或者Mapper)
           Map原理:
                在map阶段,使用job.setInputFormatClass定义的InputFormat将输入的数据集分割成小数据块splites,同时InputFormat提供一个RecordReder的实现。本例子中使用的是TextInputFormat,他提供的RecordReder会将文本的一行的行号作为key,这一行的文本作为value。这就是自定义Map的输入是<LongWritable, Text>的原因。然后调用自定义Map的map方法,将一个个<LongWritable, Text>对输入给Map的map方法。注意输出应该符合自定义Map中定义的输出<IntPair, IntWritable>。最终是生成一个List<IntPair,IntWritable>。在map阶段的最后,会先调用job.setPartitionerClass对这个List进行分区,每个分区映射到一个reducer。每个分区内又调用job.setSortComparatorClass设置 的key比较函数类排序。可以看到,这本身就是一个二次排序。如果没有通过job.setSortComparatorClass设置key比较函数类,则使用key的实现的compareTo方法。在第一个例子中,使用了IntPair实现的compareTo方法,而在下一个例子中,专门定义了key比较函数类。
                    
                 Q: map的结果发给那个reduce?谁来管理这一切?
                 A:     Partitioner用于划分键值空间(key space)。 
                        Partitioner负责控制map输出结果key的分割。Key(或者一个key子集)被用于产生分区,通常使用的是Hash函数。分区的数目与一个作业的reduce任务的数目是                          一样的。因此,它控制将中间过程的key(也就是这条记录)应该发送给m个reduce任务中的哪一个来进行reduce 操作。
         


        2. Reduce类:(继承TableReducer或者Reducer)
           Reduce的原理:在reduce阶段,reducer接收到所有映射到这个reducer的map输出后,也是会调用job.setSortComparatorClass设置的key比较函数类对所有数据对排序。然后开始构造 一个key对应的value迭代器。这时就要用到分组,使用jobjob.setGroupingComparatorClass设置的分组函数类。只要这个比较器比较的两个key相同,他们就属于  同一个组,它们的value放在一个value迭代器,而这个迭代器的key使用属于同一个组的所有key的第一个key。最后就是进入Reducer的reduce方法,reduce方法的         输入是所有的(key和它的value迭代器)。同样注意输入与输出的类型必须与自定义的Reducer中声明的一致。
reduce的输出是没有排序的。


           Q:Reduce的数目应该设置多少?
           A:           Reduce的数目建议是0.95或1.75乘以 ( * mapred.tasktracker.reduce.tasks.maximum)。用0.95,所有reduce可以在maps一完成时就立刻启动,开始传输map的输出结 果。用1.75,速度快的节点可以在完成第一轮reduce任务后,可以开始第二轮,这样可以得到比较好的负载均衡的效果。上述比例因子比整体数目稍小一些是为了给框 架中的推测性任务(speculative-tasks) 或失败的任务预留一些reduce的资源。
           Q:Reduce的三个阶段都干了什么?
           A:  Reducer有3个主要阶段:shuffle、sort和reduce。 
                
                Shuffle :Reducer的输入就是Mapper已经排好序的输出。在这个阶段,框架通过HTTP为每个Reducer获得所有Mapper输出中与之相关的分块。 (其实就是copy的过  程)
                Sort :这个阶段,框架将按照key的值对Reducer的输入进行分组 (因为不同mapper的输出中可能会有相同的key,combain保证了同一台机器相同key的合并,但是                               不同机器也可能有相同的key)。 
                           map的输出是一边被取回一边被合并的。




        3. Job 的配置:
           1.使用job.setInputFormatClass定义的InputFormat将输入的数据集分割成小数据块splites,Hadoop Map/Reduce框架为每一个Split产生一个map任务.
             Map的数目通常是由输入数据的大小决定的,一般就是所有输入文件的总块(block)数。如果你输入10TB的数据,每个块(block)的大小是 128MB,你将需要大约82,000个map来完成任务,除非使用 setNumMapTasks(int)将这个数值设置得更高。
           2.如果需要中间过程对key的分组规则和reduce前对key的分组规则不同,那么可以通过 JobConf.setOutputValueGroupingComparator(Class)来指定一个Comparator。再加上 JobConf.setOutputKeyComparatorClass(Class)可用于控制中间过程的key如何被分组,所以结合两者可以实现按值的二次排序
           3.一些作业的参数可以被直截了当地进行设置(例如: setNumReduceTasks(int)),而另一些参数则与框架或者作业的其他参数之间微妙地相互影响,并且设置起来比较复杂(例如: setNumMapTasks(int)) 
           4. Mapper和Reducer的实现可以利用Reporter 来报告进度,或者仅是表明自己运行正常。我们从界面上看到的图形就是利用Reporter来进行进度的展示。








2. HDFS  与 HBse,MapReduce 有什么关系?
        (1)HBase部署在HDFS之上。
        (2)HBase使用HDFS的方式与MapReduce使用HDFS的方式截然不同:
                MapReduce 中,首先打开HDFS文件,然后map任务流式处理文件的内容,最后关闭文件。
                HBase中,数据文件在启动时就被打开,并在处理过程中始终保持打开状态,这是为了节省每次访问操作需要打开的代价。(长开启)