Hadoop实战实例

 Hadoop 是Google MapReduce的一个Java实现。MapReduce是一种简化的分布式编程模式,让程序自动分布到一个由普通机器组成的超大集群上并发执行。就如同java程序员可以不考虑内存泄露一样, MapReduce的run-time系统会解决输入数据的分布细节,跨越机器集群的程序执行调度,处理机器的失效,并且管理机器之间的通讯请求。这样的模式允许程序员可以不需要有什么并发处理或者分布式系统的经验,就可以处理超大的分布式系统得资源。

一、概论

    作为Hadoop程序员,他要做的事情就是:
    1、定义Mapper,处理输入的Key-Value对,输出中间结果。
    2、定义Reducer,可选,对中间结果进行规约,输出最终结果。
    3、定义InputFormat 和OutputFormat,可选,InputFormat将每行输入文件的内容转换为Java类供Mapper函数使用,不定义时默认为String。
    4、定义main函数,在里面定义一个Job并运行它。

    然后的事情就交给系统了。
    1.基本概念:Hadoop的HDFS实现了google的GFS文件系统,NameNode作为文件系统的负责调度运行在master,DataNode运行在每个机器上。同时Hadoop实现了Google的MapReduce,JobTracker作为MapReduce的总调度运行在master,TaskTracker则运行在每个机器上执行Task。
    2.main()函数,创建JobConf,定义Mapper,Reducer,Input/OutputFormat 和输入输出文件目录,最后把Job提交給JobTracker,等待Job结束。
    3.JobTracker,创建一个InputFormat的实例,调用它的getSplits()方法,把输入目录的文件拆分成FileSplist作为Mapper task 的输入,生成Mapper task加入Queue。
    4.TaskTracker 向 JobTracker索求下一个Map/Reduce。
     Mapper Task先从InputFormat创建RecordReader,循环读入FileSplits的内容生成Key与Value,传给Mapper函数,处理完后中间结果写成SequenceFile.
     Reducer Task 从运行Mapper的TaskTracker的Jetty上使用http协议获取所需的中间内容(33%),Sort/Merge后(66%),执行Reducer函数,最后按照OutputFormat写入结果目录。 

      TaskTracker 每10秒向JobTracker报告一次运行情况,每完成一个Task10秒后,就会向JobTracker索求下一个Task。

      Nutch项目的全部数据处理都构建在Hadoop之上,详见Scalable Computing with Hadoop

二、程序员编写的代码

 (可以查看hadoop-examples-0.20.203.0.jar,里面也有一个类grep)

    我们做一个简单的分布式的Grep,简单对输入文件进行逐行的正则匹配,如果符合就将该行打印到输出文件。因为是简单的全部输出,所以我们只要写Mapper函数,不用写Reducer函数,也不用定义Input/Output Format。

package  demo.hadoop  
public   class  HadoopGrep {  
     public   static   class  RegMapper  extends  MapReduceBase  implements  Mapper {  
               private  Pattern pattern;  
               public   void  configure(JobConf job) {  
                         pattern  =  Pattern.compile(job.get( " mapred.mapper.regex " ));  
              }  
              public   void  map(WritableComparable key, Writable value, OutputCollector output, Reporter reporter)  
                     throws  IOException {  
                         String text  =  ((Text) value).toString();  
                         Matcher matcher  =  pattern.matcher(text);  
                       if  (matcher.find()) {  
                        output.collect(key, value);  
             }  
    }  
 }  
  
  private  HadoopGrep () {  
 }  //  singleton   
  
public   static   void  main(String[] args)  throws  Exception {  
  JobConf grepJob  =   new  JobConf(HadoopGrep. class );  
  grepJob.setJobName( " grep-search " );  
  grepJob.set( " mapred.mapper.regex " , args[ 2 ]);  
  
  grepJob.setInputPath( new  Path(args[ 0 ]));  
  grepJob.setOutputPath( new  Path(args[ 1 ]));  
  grepJob.setMapperClass(RegMapper. class );  
  grepJob.setReducerClass(IdentityReducer. class );  
  JobClient.runJob(grepJob);  
 }  
}

          RegMapper类的configure()函数接受由main函数传入的查找字符串,map() 函数进行正则匹配,key是行数,value是文件行的内容,符合的文件行放入中间结果。
        main()函数定义由命令行参数传入的输入输出目录和匹配字符串,Mapper函数为RegMapper类,Reduce函数是什么都不做,直接把中间结果输出到最终结果的的IdentityReducer类,运行Job。

整个代码非常简单,丝毫没有分布式编程的任何细节。

三.运行Hadoop程序

        Hadoop这方面的文档写得不全面,综合参考GettingStartedWithHadoop 与Nutch Hadoop Tutorial 两篇后,再碰了很多钉子才终于完整的跑起来了,记录如下:     
3.1 local运行模式
       完全不进行任何分布式计算,不动用任何namenode,datanode的做法,适合一开始做调试代码。
       解压hadoop,其中conf目录是配置目录,hadoop的配置文件在hadoop-default.xml,如果要修改配置,不是直接修改该文件,而是修改hadoop-site.xml,将该属性在hadoop-site.xml里重新赋值。
       hadoop-default.xml的默认配置已经是local运行,不用任何修改,配置目录里唯一必须修改的是hadoop-env.sh 里JAVA_HOME的位置。
       将编译好的HadoopGrep与RegMapper.class 放入hadoop/build/classes/demo/hadoop/目录 

        或者编译成jar包HadoopGrep.jar放入hadoop/build/classes/demo/hadoop/目录

        找一个比较大的xx.log文件放,然后运行

        bin/hadoop demo.hadoop.HadoopGrep  input   /tmp/out  "[a-b]"
        (jar包运行:bin/hadoop jar HadoopGrep.jar  HadoopGrep  input   /tmp/output  "[a-b]" )
        说明:
         input  为xx.log文件所在目录 
         /tmp/output为输出目录 
         "[a-b]"   grep的字符串 

        查看输出目录的结果,查看hadoop/logs/里的运行日志。  
        在重新运行前,先删掉输出目录。

  3.2 集群运行模式

    (查看集群配置:http://blog.csdn.net/hguisu/article/details/7237395)

      1 )执行bin/hadoop dfs 可以看到它所支持的文件操作指令。   

      2) 创建目录输入inpu:   
           $ bin/hadoop dfs -mkdir input    

      3)上传文件xx.log到指定目录 input :   
           $ bin/hadoop dfs -put xx.log input

       4 )  执行 bin/hadoop demo.hadoop.HadoopGrep input  output
             (jar包运行:bin/hadoop jar HadoopGrep.jar  HadoopGrep  input   /tmp/output  "[a-b]" )

       5 ) 查看输出文件:

           将输出文件从分布式文件系统拷贝到本地文件系统查看:
            $ bin/hadoop fs -get output output
            $ cat output/*

            或者
            在分布式文件系统上查看输出文件:
            $ bin/hadoop fs -cat output/*

            重新执行前,运行hadoop/bin/hadoop dfs -rm output删除output目录

       7.运行hadoop/bin/stop-all.sh 结束。

四、效率

    经测试,Hadoop并不是万用灵丹,很取决于文件的大小和数量,处理的复杂度以及群集机器的数量,相连的带宽,当以上四者并不大时,hadoop优势并不明显。
    比如,不用hadoop用java写的简单grep函数处理100M的log文件只要4秒,用了hadoop local的方式运行是14秒,用了hadoop单机集群的方式是30秒,用双机集群10M网口的话更慢,慢到不好意思说出来的地步。

转自:http://blog.csdn.net/hguisu/article/details/7239390

原创文章,作者:s19930811,如若转载,请注明出处:http://www.178linux.com/3106

(0)
s19930811s19930811
上一篇 2015-04-13 22:52
下一篇 2015-04-13 22:52

相关推荐

  • linux进程管理

    Linux内核:抢占式多任务 进程类型: 1、守护进程:在系统引导过程中启动的进程,与终端无关的进程; 2、前台进程:跟终端相关,通过终端启动的进程,注意:也可把前台启动的进程送往后台,以守护模式运行;   进程状态: 运行态:running 就绪态:ready 睡眠态:a、可中断:interruptable;b、不可中断:uninterrupta…

    Linux干货 2018-02-08
  • 马哥教育网络班22期+第三周课程练习

    1、列出当前系统上所有已经登录的用户的用户名,注意:同一个用户登录多次,则只显示一次即可。     [root@zabbix ~]# who|awk '{print $1}'|sort| uniq 2、取出最后登录到当前系统的用户的相关信息。 &nb…

    Linux干货 2016-08-23
  • N22-第6周作业-冥界之王

    请详细总结vim编辑器的使用并完成以下练习题1、复制/etc/rc.d/rc.sysinit文件至/tmp目录,将/tmp/rc.sysinit文件中的以至少一个空白字符开头的行的行首加#;    [root@CentOS6 /]# cp /etc/rc.d/rc.sysinit /tmp…

    Linux干货 2016-09-19
  • 马哥教育网络班22期第二周课程练习1-未闻花名

    1、Linux管理文件和目录的命令 命令 功能 命令 功能 pwd 显示当前目录 ls 查看目录下的内容 cd 改变所在目录 cat 显示文件的内容 grep 在文件中查找某字符 cp 复制文件 touch 创建文件 mv 移动文件 rm 删除文件 rmdir 删除目录 1.1 pwd命令 该命令的英文解释为print working directory(打…

    Linux干货 2016-08-22
  • linux的发展史

                  linux的发展史     1  Linux的诞生:    1988年:芬兰赫尔辛基大学迎来一位新生-linus benedict torvalds (后面简称linus)   2 &nbsp…

    Linux干货 2016-10-19
  • 第六周博客作业

                   1、复制/etc/rc.d/rc.sysinit文件至/tmp目录,将/tmp/rc.sysinit文件中的以至少一个空白字符开头的行的行首加#; %s@^[[:space:]]\+[^[:…

    Linux干货 2016-12-05