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

相关推荐

  • 8.3_Linux习题和作业

    课堂习题 1.当用户xiaoming对/testdir 目录无执行权限时,意味着无法做哪些操作? 答:不能cd进该目录 2.当用户xiaoqiang对/testdir 目录无读权限时,意味着无法做哪些操作? 答:不能查看目录内的文件列表,不能cd,也不能查看目录里面文件的元数据 3.当用户wangcai 对/testdir 目录无写权限时,该目录下的只读文件…

    Linux干货 2016-08-04
  • tar ,cpio打包解压. shell脚本for,while,until循环. rpm包管理,循环的特殊用法. select循环菜单,函数function,rpm包查询,yum

    tar  tar -cf 路径+文件名字后续.tar  +路径 创建归档压缩 tar cf /testdir/etc.tar /etc/ tar cvf 可以查看解压过程 tar tvf 预览作用 tar xvf 解压文件  tar zcvf /testdir/etc2.tar.gz /etc/ 解压再压缩到指定路径,文件格式 …

    Linux干货 2016-08-21
  • Linux终端和伪终端简述

    本文简述Linux各种类型终端的区别以及如何用命令查看终端类型

    Linux干货 2018-03-26
  • 用一条命令’pwd’判断并证明系统命令的执行顺序。

    一、命令分类        在Linux系统中命令分为两类:            1.内部命令:shell buildin 每次启动系统都会重新加载入内存。        2.外部命令:即某目录下的…

    Linux干货 2017-09-03
  • 位置变量在Shell脚本编程中的作用

    位置变量:         如果要向一个shell脚本传递信息,可以使用位置参数完成此功能;参数相关数目传入脚本,此数目可以任意多,但只有前9个可以被访问,使用shift命令可以改变这个限制;参数从第一个开始,在第九个结束;每个访问参数前要加$符号;第一个参数为0,表示预留保存实…

    Linux干货 2016-08-15
  • N28-第二周作业

    1、Linux上的文件管理类命令都有哪些,其常用的使用方法及其相关示例演示。
    2、bash的工作特性之命令执行状态返回值和命令行展开所涉及的内容及其示例演示。
    3、请使用命令行展开功能来完成以下练习:
    (1)、创建/tmp目录下的:a_c, a_d, b_c, b_d
    (2)、创建/tmp/mylinux目录下的:
    mylinux/
    ├── bin
    ├── boot
    │   └── grub
    ├── dev
    ├── etc
    │   ├── rc.d
    │   │   └── init.d
    │   └── sysconfig
    │   └── network-scripts
    ├── lib
    │   └── modules
    ├── lib64
    ├── proc
    ├── sbin
    ├── sys
    ├── tmp
    ├── usr
    │   └── local
    │   ├── bin
    │   └── sbin
    └── var
    ├── lock
    ├── log
    └── run
    4、文件的元数据信息有哪些,分别表示什么含义,如何查看?如何修改文件的时间戳信息。
    5、如何定义一个命令的别名,如何在命令中引用另一个命令的执行结果?
    6、显示/var目录下所有以l开头,以一个小写字母结尾,且中间至少出现一位数字(可以有其它字符)的文件或目录。
    7、显示/etc目录下,以任意一个数字开头,且以非数字结尾的文件或目录。
    8、显示/etc目录下,以非字母开头,后面跟了一个字母以及其它任意长度任意字符的文件或目录。
    9、在/tmp目录下创建以tfile开头,后跟当前日期和时间的文件,文件名形如:tfile-2016-05-27-09-32-22。
    10、复制/etc目录下所有以p开头,以非数字结尾的文件或目录到/tmp/mytest1目录中。
    11、复制/etc目录下所有以.d结尾的文件或目录至/tmp/mytest2目录中。
    12、复制/etc/目录下所有以l或m或n开头,以.conf结尾的文件至/tmp/mytest3目录中。

    Linux干货 2017-12-11