目录
利用命令行,测试WourdCount程序:
1、创建Wordcount示例文件
2、Map Task的整体流程:
3、Reduce的整体流程:
首页 数据库 mysql教程 hadoop学习(六)WordCount示例深度学习MapReduce过程(1)

hadoop学习(六)WordCount示例深度学习MapReduce过程(1)

Jun 07, 2016 pm 03:29 PM
hadoop 学习 深度 示例

花了整整一个下午(6个多小时),整理总结,也算是对这方面有一个深度的了解。日后可以回头多看看。 我们都安装完Hadoop之后,按照一些案例先要跑一个WourdCount程序,来测试Hadoop安装是否成功。在终端中用命令创建一个文件夹,简单的向两个文件中各写入一

花了整整一个下午(6个多小时),整理总结,也算是对这方面有一个深度的了解。日后可以回头多看看。

我们都安装完Hadoop之后,按照一些案例先要跑一个WourdCount程序,来测试Hadoop安装是否成功。在终端中用命令创建一个文件夹,简单的向两个文件中各写入一段话,然后运行Hadoop,WourdCount自带WourdCount程序指令,就可以输出写入的那句话各个不同单词的个数。但是这不是这篇博客主要讲的内容,主要是想通过一个简单的Wordcount程序,来认识Hadoop的内部机制。并通过此来深入了解MapReduce的详细过程。在Thinking in BigDate(八)大数据Hadoop核心架构HDFS+MapReduce+Hbase+Hive内部机理详解中我们已经很大概梳理一下,Hadoop内部集群架构,并对MapReduce也有初步的了解,这里我们以WourdCount程序来深入的探讨MapReduce的过程。

利用命令行,测试WourdCount程序:

WourdCount程序就是统计文本中字母的个数

1、创建Wordcount示例文件

zhangzhen@ubuntu:~/software$ mkdir input
zhangzhen@ubuntu:~/software$ cd input/
zhangzhen@ubuntu:~/software/input$ echo "I am zhangzhen">test1.txt
zhangzhen@ubuntu:~/software/input$ echo "You are not zhangzhen">test2.txt
zhangzhen@ubuntu:~/software/input$ cd ../hadoop-1.2.1/
zhangzhen@ubuntu:~/software/hadoop-1.2.1$ cd bin
zhangzhen@ubuntu:~/software/hadoop-1.2.1/bin$ ls
hadoop             slaves.sh                  start-mapred.sh           stop-mapred.sh
hadoop-config.sh   start-all.sh               stop-all.sh               task-controller
hadoop-daemon.sh   start-balancer.sh          stop-balancer.sh
hadoop-daemons.sh  start-dfs.sh               stop-dfs.sh
rcc                start-jobhistoryserver.sh  stop-jobhistoryserver.sh
zhangzhen@ubuntu:~/software/hadoop-1.2.1/bin$ jps(确定Hadoop已经起来了)
7101 SecondaryNameNode
7193 JobTracker
7397 TaskTracker
9573 Jps
6871 DataNode
6667 NameNode
zhangzhen@ubuntu:~/software/hadoop-1.2.1/bin$ cd ..
zhangzhen@ubuntu:~/software/hadoop-1.2.1$ ls
bin          data                       hadoop-minicluster-1.2.1.jar  libexec      share
build.xml    docs                       hadoop-test-1.2.1.jar         LICENSE.txt  src
c++          hadoop-ant-1.2.1.jar       hadoop-tools-1.2.1.jar        logs         webapps
CHANGES.txt  hadoop-client-1.2.1.jar    ivy                           NOTICE.txt
conf         hadoop-core-1.2.1.jar      ivy.xml                       README.txt
contrib      hadoop-examples-1.2.1.jar  lib                           sbin
zhangzhen@ubuntu:~/software/hadoop-1.2.1$ bin/hadoop dfs -put ../input in  //把文件上传的hdfa中的in目录中,其实这个说法有误
zhangzhen@ubuntu:~/software/hadoop-1.2.1$ bin/hadoop dfs -ls .in/*
ls: Cannot access .in/*: No such file or directory.
zhangzhen@ubuntu:~/software/hadoop-1.2.1$ bin/hadoop dfs -ls ./in/*
-rw-r--r--   1 zhangzhen supergroup         15 2014-03-22 10:45 /user/zhangzhen/in/test1.txt
-rw-r--r--   1 zhangzhen supergroup         22 2014-03-22 10:45 /user/zhangzhen/in/test2.txt 

登录后复制

注意:Hadoop中是没有当前目录这个概念的。所以上传到hdfs中的文件,我们是不能通过cd命令、ls命令,查看目录中的文件。这里我们通过就是上面和下面命令查看hdfs中文件的方法。

在每个版本中,hadoop-examples-1.2.1.jar的位置不一样,在Hadoop1.2.1版本中,我们hadoop-examples-1.2.1.jar文件是在Hadoop目录中的,这里我们需要把这个hadoop-examples-1.2.1.jar拷贝到/bin 目录中。

执行:利用hadoop-examples-1.2.1.jar执行bin目录下in目录中的文件,并把结果写入到 put 的文件夹。

zhangzhen@ubuntu:~/software$ bin/hadoop jar hadoop-examples-1.2.1.jar wordcount in put

登录后复制

查看输出的结果:

zhangzhen@ubuntu:~/software/hadoop-1.2.1$ bin/hadoop dfs -ls
Found 2 items
drwxr-xr-x   - zhangzhen supergroup          0 2014-03-22 10:45 /user/zhangzhen/in
drwxr-xr-x   - zhangzhen supergroup          0 2014-03-22 10:56 /user/zhangzhen/put
zhangzhen@ubuntu:~/software/hadoop-1.2.1$ bin/hadoop dfs -ls ./put
Found 3 items
-rw-r--r--   1 zhangzhen supergroup          0 2014-03-22 10:56 /user/zhangzhen/put/_SUCCESS
drwxr-xr-x   - zhangzhen supergroup          0 2014-03-22 10:56 /user/zhangzhen/put/_logs  目录
-rw-r--r--   1 zhangzhen supergroup         39 2014-03-22 10:56 /user/zhangzhen/put/part-r-00000   这是文件
zhangzhen@ubuntu:~/software/hadoop-1.2.1/hadoop dfs -cat ./put/*
I      1
You    1
am     1
are    1
not    1
zhangzhen    2
cat: File does not exist: /user/zhangzhen/put/_logs
zhangzhen@ubuntu:~/software/hadoop-1.2.1$ 

登录后复制

上面的结果,就基本可以证明Hadoop搭建是没有问题的。执行hadoop-examples-1.2.1.jar程序,其实是把java程序编译打成一个jar文件,然后直接运行,就可以得到结果。其实这也是以后我们运行java程序的一个方法。把程序编译打包上传,然后运行。还有另一种方面,eclipse连接Hadoop,可以联机测试。两种方法各有优点,不再详述。

运行的程序,我们可以在Hadoop的安装目录中找到源文件,WourdCount.java源代码。

zhangzhen@ubuntu:~/software/hadoop-1.2.1/src/examples/org/apache/hadoop/examples$ pwd 
/home/zhangzhen/software/hadoop-1.2.1/src/examples/org/apache/hadoop/examples 
zhangzhen@ubuntu:~/software/hadoop-1.2.1/src/examples/org/apache/hadoop/examples$ 

登录后复制

下面是把源代码拷到eclipse程序中,利用此代码(并未修改)测试一下实际的数据并得到结果。(注释是对上以一行的解释)

import java.io.IOException;  
import java.util.StringTokenizer;  
  
import org.apache.hadoop.conf.Configuration;  
import org.apache.hadoop.fs.Path;  
import org.apache.hadoop.io.IntWritable;  
import org.apache.hadoop.io.Text;  
import org.apache.hadoop.mapreduce.Job;  
import org.apache.hadoop.mapreduce.Mapper;  
import org.apache.hadoop.mapreduce.Reducer;  
import org.apache.hadoop.mapreduce.lib.input.FileInputFormat;  
import org.apache.hadoop.mapreduce.lib.output.FileOutputFormat;  
import org.apache.hadoop.util.GenericOptionsParser;  
  
public class Wordcount {  
  
  public static class TokenizerMapper   
       extends Mapper<Object, Text, Text, IntWritable>{ 
//规定map中用到的数据类型,这里的Text相当于jdk中的String IntWritable相当于jdk的int类型,
//这样做的原因主要是为了hadoop的数据序化而做的。 
      
    private final static IntWritable one = new IntWritable(1);
//声时一个IntWritable变量,作计数用,每出现一个key,给其一个value=1的值  
    private Text word = new Text();//用来暂存map输出中的key值,Text类型的  
        
    public void map(Object key, Text value, Context context  
                    ) throws IOException, InterruptedException { 
//这就是map函数,它是和Mapper抽象类中的相对应的,此处的Object key,Text value的类型和上边的Object,
//Text是相对应的,而且最好一样,不然的话,多数情况运行时会报错。
      StringTokenizer itr = new StringTokenizer(value.toString());
//Hadoop读入的value是以行为单位的,其key为该行所对应的行号,因为我们要计算每个单词的数目,
//默认以空格作为间隔,故用StringTokenizer辅助做字符串的拆分,也可以用string.split("")来作。
      while (itr.hasMoreTokens()) { //遍历一下每行字符串中的单词 
        word.set(itr.nextToken());  //出现一个单词就给它设成一个key并将其值设为1
        context.write(word, one);   //输出设成的key/value值
//上面就是map打散的过程
      }  
    }  
  }  
    
  public static class IntSumReducer   
       extends Reducer<Text,IntWritable,Text,IntWritable> {
//reduce的静态类,这里和Map中的作用是一样的,设定输入/输出的值的类型
    private IntWritable result = new IntWritable();  
  
    public void reduce(Text key, Iterable<IntWritable> values,   
                       Context context  
                       ) throws IOException, InterruptedException {  
      int sum = 0;  
      for (IntWritable val : values) { 
 //由于map的打散,这里会得到如,{key,values}={"hello",{1,1,....}},这样的集合
        sum += val.get();               
//这里需要逐一将它们的value取出来予以相加,取得总的出现次数,即为汇和
      }  
      result.set(sum);                  //将values的和取得,并设成result对应的值
      context.write(key, result);
//此时的key即为map打散之后输出的key,没有变化,变化的时result,以前得到的是一个数字的集合,
//已经给算出和了,并做为key/value输出。  
    }  
  }  
  
  public static void main(String[] args) throws Exception {  
    Configuration conf = new Configuration();  //取得系统的参数
    String[] otherArgs = new GenericOptionsParser(conf, args).getRemainingArgs();  
    if (otherArgs.length != 2) {               
 //判断一下命令行输入路径/输出路径是否齐全,即是否为两个参数
      System.err.println("Usage: wordcount <in> <out>");  
      System.exit(2);                           //若非两个参数,即退出
    }  
    Job job = new Job(conf, "word count");      
//此程序的执行,在hadoop看来是一个Job,故进行初始化job操作
    job.setJarByClass(Wordcount.class);        
 //可以认为成,此程序要执行MyWordCount.class这个字节码文件
    job.setMapperClass(TokenizerMapper.class); 
//在这个job中,我用TokenizerMapper这个类的map函数
    job.setCombinerClass(IntSumReducer.class);  
    job.setReducerClass(IntSumReducer.class);   
//在这个job中,我用IntSumReducer这个类的reduce函数 
    job.setOutputKeyClass(Text.class);          
//在reduce的输出时,key的输出类型为Text
    job.setOutputValueClass(IntWritable.class);  
//在reduce的输出时,value的输出类型为IntWritable
    FileInputFormat.addInputPath(job, new Path(otherArgs[0]));  
//初始化要计算word的文件的路径
    FileOutputFormat.setOutputPath(job, new Path(otherArgs[1])); 
//初始化要计算word的文件的之后的结果的输出路径 
    System.exit(job.waitForCompletion(true) ? 0 : 1);
 //提交job到hadoop上去执行了,意思是指如果这个job真正的执行完了则主函数退出了,若没有真正的执行完就退出了。  
  } 
//参考:http://hi.baidu.com/erliang20088/item/ce550f2f088ff1ce0e37f930
}

登录后复制

WourdCount程序中隐藏的秘密

1、具体流程:

1)文件拆分成splits,由于测试用的文件较小,所以每个文件为一个split,并将文件按行分割形成 对,如下图。这一步由MapReduce框架自动完成,其中偏移量(即key值)包括了回车所占的字符数和Linux环境有关。

\

2)将分割好的对交给用户定义的map方法进行处理,生成新的对。

\

3)得到map方法输出的对后,Mapper会将它们按照key值进行排序,并执行Combine过程,将key至相同value值累加,得到Mapper的最终输出结果。

\

2、Map Task的整体流程:

可以概括为5个步骤:

1)Read:Map Task通过用户编写的RecordReader,从输入InputSplit中解析出一个个key/value。

2)Map:该阶段主要将解析出的key/value交给用户编写的map()函数处理,并产生一系列的key/value。

3)Collect:在用户编写的map()函数中,当数据处理完成后,一般会调用OutputCollector.collect()输入结果。在该函数内部,它会将生成的key/value分片(通过Partitioner),并写入一个环形内存缓冲区中。

4)Spill:即“溢写”,当环形缓冲区满后,MapReduce会将数据写到本地磁盘上,生成一个临时文件。将数据写入本地磁盘之前,先要对数据进行一次本地排序,并在必要时对数据进行合并,压缩等操作。

5)Combine:当所有数据处理完成后,Map Task对所有临时文件进行一次合并,以确保最终只会生成一个数据文件。

3、Reduce的整体流程:

可以概括为5个步骤:

1)Shuffle:也称Copy阶段。Reduce Task从各个Map Task上远程拷贝一片数据,并针对某一片数据,如果其大小超过一定阀值,则写到磁盘上,否则直接放到内存中。

2)Merge:在远程拷贝的同时,Reduce Task启动了两个后台线程对内存和磁盘上的文件进行合并,以防止内存使用过多或者磁盘上文件过多。

3)Sort:按照MapReduce语义,用户编写的reduce()函数输入数据是按key进行聚集的一组数据。为了将key相同的数据聚在一 起,Hadoop采用了基于排序的策略。由于各个Map Task已经实现了对自己的处理结果进行了局部排序,因此,Reduce Task只需对所有数据进行一次归并排序即可。

4)Reduce:在该阶段中,Reduce Task将每组数据依次交给用户编写的reduce()函数处理。

5)Write:reduce()函数将计算结果写到HDFS。

通过一些博客对WourdCount的介绍示例,总结Map、Reduce的整个过程。加上Thinking in BigDate(八)大数据Hadoop核心架构HDFS+MapReduce+Hbase+Hive内部机理详解所将的内容,大致把整个文件数据处理的过程梳理一遍。但是还有很多细节没有讲明。如:Spill、Combine、Shuffle的过程,Shuffle整个MapReduce的核心。接下来,我们更深入了解MapReduce的过程,更深入的了解,便于我们在以后在操作Hadoop集群的过程中,有利于系统调优,甚至修改Hadoop源代码。

Copyright?BUAA
本站声明
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn

热AI工具

Undresser.AI Undress

Undresser.AI Undress

人工智能驱动的应用程序,用于创建逼真的裸体照片

AI Clothes Remover

AI Clothes Remover

用于从照片中去除衣服的在线人工智能工具。

Undress AI Tool

Undress AI Tool

免费脱衣服图片

Clothoff.io

Clothoff.io

AI脱衣机

Video Face Swap

Video Face Swap

使用我们完全免费的人工智能换脸工具轻松在任何视频中换脸!

热工具

记事本++7.3.1

记事本++7.3.1

好用且免费的代码编辑器

SublimeText3汉化版

SublimeText3汉化版

中文版,非常好用

禅工作室 13.0.1

禅工作室 13.0.1

功能强大的PHP集成开发环境

Dreamweaver CS6

Dreamweaver CS6

视觉化网页开发工具

SublimeText3 Mac版

SublimeText3 Mac版

神级代码编辑软件(SublimeText3)

Oracle DECODE函数详解及用法示例 Oracle DECODE函数详解及用法示例 Mar 08, 2024 pm 03:51 PM

Oracle中的DECODE函数是一种条件表达式,常用于在查询语句中根据不同的条件返回不同的结果。本文将详细介绍DECODE函数的语法、用法和示例代码。一、DECODE函数语法DECODE(expr,search1,result1[,search2,result2,...,default])expr:要进行比较的表达式或字段。search1,

Go语言的缩进规范及示例 Go语言的缩进规范及示例 Mar 22, 2024 pm 09:33 PM

Go语言的缩进规范及示例Go语言是一种由Google开发的编程语言,它以简洁、清晰的语法着称,其中缩进规范在代码的可读性和美观性方面起着至关重要的作用。本文将介绍Go语言的缩进规范,并通过具体的代码示例进行详细说明。缩进规范在Go语言中,缩进使用制表符(tab)而非空格。每级缩进为一个制表符,通常设置为4个空格的宽度。这样的规范统一了代码风格,使得团队合作编

Pygame入门指南:全面安装和配置教程 Pygame入门指南:全面安装和配置教程 Feb 19, 2024 pm 10:10 PM

从零开始学习Pygame:完整的安装和配置教程,需要具体代码示例引言:Pygame是一个使用Python编程语言开发的开源游戏开发库,它提供了丰富的功能和工具,使得开发者可以轻松创建各种类型的游戏。本文将带您从零开始学习Pygame,并提供完整的安装和配置教程,以及具体的代码示例,让您快速入门。第一部分:安装Python和Pygame首先,确保您的计算机上已

一起学习word根号输入办法 一起学习word根号输入办法 Mar 19, 2024 pm 08:52 PM

在word中编辑文字内容时,有时会需要输入公式符号。有的小伙们不知道在word根号输入的方法,小面就让小编跟小伙伴们一起分享下word根号输入的方法教程。希望对小伙伴们有所帮助。首先,打开电脑上的Word软件,然后打开要编辑的文件,并将光标移动到需要插入根号的位置,参考下方的图片示例。2.选择【插入】,再选择符号里的【公式】。如下方的图片红色圈中部分内容所示:3.接着选择下方的【插入新公式】。如下方的图片红色圈中部分内容所示:4.选择【根式】,再选择合适的根号。如下方的图片红色圈中部分内容所示:

揭秘C语言的吸引力: 发掘程序员的潜质 揭秘C语言的吸引力: 发掘程序员的潜质 Feb 24, 2024 pm 11:21 PM

学习C语言的魅力:解锁程序员的潜力随着科技的不断发展,计算机编程已经成为了一个备受关注的领域。在众多编程语言中,C语言一直以来都备受程序员的喜爱。它的简单、高效以及广泛应用的特点,使得学习C语言成为了许多人进入编程领域的第一步。本文将讨论学习C语言的魅力,以及如何通过学习C语言来解锁程序员的潜力。首先,学习C语言的魅力在于其简洁性。相比其他编程语言而言,C语

PHP 点操作符的运用与实例分析 PHP 点操作符的运用与实例分析 Mar 28, 2024 pm 12:06 PM

PHP点操作符的运用与实例分析在PHP中,点操作符(“.”)是用来连接两个字符串的运算符,它在字符串拼接时非常常用并且十分灵活。通过使用点操作符,我们可以方便地将多个字符串连接起来,构成一个新的字符串。下面将通过实例分析来介绍PHP点操作符的运用。一、基本使用方法首先,我们来看一个基本的使用实例。假设有两个变量$str1和$str2,分别存储了两个字

从零开始学习Go语言中的main函数 从零开始学习Go语言中的main函数 Mar 27, 2024 pm 05:03 PM

标题:从零开始学习Go语言中的main函数Go语言作为一种简洁、高效的编程语言,备受开发者青睐。在Go语言中,main函数是一个入口函数,每个Go程序都必须包含main函数作为程序的入口点。本文将从零开始介绍如何学习Go语言中的main函数,并提供具体的代码示例。一、首先,我们需要安装Go语言的开发环境。可以前往官方网站(https://golang.org

Curl Get命令的示例 Curl Get命令的示例 Mar 20, 2024 pm 06:56 PM

在Linux中,URL或Curl客户端是一个流行的命令行实用程序,允许您使用HTTPS、HTTP、FTP等多种协议在网络上传输数据。它允许您使用其get、post和request方法发送和接收数据。其中,你需要经常使用“get”方法。因此,学习各种方法和各种选项,你可以用来提高你的生产力变得至关重要。“执行卷曲操作非常简单,只需输入几个简单的命令即可完成。尽管这看似简单,但许多用户并未充分认识到其潜力。因此,这篇简短指南提供了一些关于在Linux系统中使用“curlget”命令的实例。”Curl

See all articles