当前位置: 首页 > 编程日记 > 正文

初学Hadoop之图解MapReduce与WordCount示例分析

Hadoop的框架最核心的设计就是:HDFS和MapReduce。HDFS为海量的数据提供了存储,MapReduce则为海量的数据提供了计算。
HDFS是Google File System(GFS)的开源实现,MapReduce是Google MapReduce的开源实现。
HDFS和MapReduce实现是完全分离的,并不是没有HDFS就不能MapReduce运算。
本文主要参考了以下三篇博客学习整理而成。
1、Hadoop示例程序WordCount详解及实例
2、hadoop 学习笔记:mapreduce框架详解
3、hadoop示例程序wordcount分析

1、MapReduce整体流程

最简单的MapReduce应用程序至少包含 3 个部分:一个 Map 函数、一个 Reduce 函数和一个 main 函数。在运行一个mapreduce计算任务时候,任务过程被分为两个阶段:map阶段和reduce阶段,每个阶段都是用键值对(key/value)作为输入(input)和输出(output)。main 函数将作业控制和文件输入/输出结合起来。
  • 并行读取文本中的内容,然后进行MapReduce操作。
  • Map过程:并行读取文本,对读取的单词进行map操作,每个词都以<key,value>形式生成。

我的理解:

一个有三行文本的文件进行MapReduce操作。

读取第一行Hello World Bye World ,分割单词形成Map。

<Hello,1> <World,1> <Bye,1> <World,1>

读取第二行Hello Hadoop Bye Hadoop ,分割单词形成Map。

<Hello,1> <Hadoop,1> <Bye,1> <Hadoop,1>

读取第三行Bye Hadoop Hello Hadoop,分割单词形成Map。

<Bye,1> <Hadoop,1> <Hello,1> <Hadoop,1>

  • Reduce操作是对map的结果进行排序,合并,最后得出词频。

我的理解:

经过进一步处理(combiner),将形成的Map根据相同的key组合成value数组。

<Bye,1,1,1> <Hadoop,1,1,1,1> <Hello,1,1,1> <World,1,1>

循环执行Reduce(K,V[]),分别统计每个单词出现的次数。

<Bye,3> <Hadoop,4> <Hello,3> <World,2>

2、WordCount源码

package org.apache.hadoop.examples;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;
/*** * 描述:WordCount explains by York* @author Hadoop Dev Group*/
publicclass WordCount {/*** 建立Mapper类TokenizerMapper继承自泛型类Mapper* Mapper类:实现了Map功能基类* Mapper接口:* WritableComparable接口:实现WritableComparable的类可以相互比较。所有被用作key的类应该实现此接口。* Reporter 则可用于报告整个应用的运行进度,本例中未使用。 * */publicstaticclass TokenizerMapper extends Mapper<Object, Text, Text, IntWritable>{/*** IntWritable, Text 均是 Hadoop 中实现的用于封装 Java 数据类型的类,这些类实现了WritableComparable接口,* 都能够被串行化从而便于在分布式环境中进行数据交换,你可以将它们分别视为int,String 的替代品。* 声明one常量和word用于存放单词的变量*/privatefinalstatic IntWritable one =new IntWritable(1);private Text word =new Text();/*** Mapper中的map方法:* void map(K1 key, V1 value, Context context)* 映射一个单个的输入k/v对到一个中间的k/v对* 输出对不需要和输入对是相同的类型,输入对可以映射到0个或多个输出对。* Context:收集Mapper输出的<k,v>对。* Context的write(k, v)方法:增加一个(k,v)对到context* 程序员主要编写Map和Reduce函数.这个Map函数使用StringTokenizer函数对字符串进行分隔,通过write方法把单词存入word中* write方法存入(单词,1)这样的二元组到context中*/  publicvoid map(Object key, Text value, Context context) throws IOException, InterruptedException {StringTokenizer itr =new StringTokenizer(value.toString());while (itr.hasMoreTokens()) {word.set(itr.nextToken());context.write(word, one);}}}publicstaticclass IntSumReducer extends Reducer<Text,IntWritable,Text,IntWritable> {private IntWritable result =new IntWritable();/*** Reducer类中的reduce方法:* void reduce(Text key, Iterable<IntWritable> values, Context context)* 中k/v来自于map函数中的context,可能经过了进一步处理(combiner),同样通过context输出           */publicvoid reduce(Text key, Iterable<IntWritable> values, Context context) throws IOException, InterruptedException {int sum =0;for (IntWritable val : values) {sum += val.get();}result.set(sum);context.write(key, result);}}publicstaticvoid main(String[] args) throws Exception {/*** Configuration:map/reduce的j配置类,向hadoop框架描述map-reduce执行的工作*/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");    //设置一个用户定义的job名称job.setJarByClass(WordCount.class);job.setMapperClass(TokenizerMapper.class);    //为job设置Mapper类job.setCombinerClass(IntSumReducer.class);    //为job设置Combiner类job.setReducerClass(IntSumReducer.class);    //为job设置Reducer类job.setOutputKeyClass(Text.class);        //为job的输出数据设置Key类job.setOutputValueClass(IntWritable.class);    //为job输出设置value类FileInputFormat.addInputPath(job, new Path(otherArgs[0]));    //为job设置输入路径FileOutputFormat.setOutputPath(job, new Path(otherArgs[1]));//为job设置输出路径System.exit(job.waitForCompletion(true) ?0 : 1);        //运行job
  }
}

3、WordCount逐行解析

  • 对于map函数的方法。
public void map(Object key, Text value, Context context) throws IOException, InterruptedException {…}

这里有三个参数,前面两个Object key, Text value就是输入的key和value,第三个参数Context context这是可以记录输入的key和value,例如:context.write(word, one);此外context还会记录map运算的状态。

  • 对于reduce函数的方法。
public void reduce(Text key, Iterable<IntWritable> values, Context context) throws IOException, InterruptedException {…}

reduce函数的输入也是一个key/value的形式,不过它的value是一个迭代器的形式Iterable<IntWritable> values,也就是说reduce的输入是一个key对应一组的值的value,reduce也有context和map的context作用一致。

至于计算的逻辑则需要程序员编码实现。

  • 对于main函数的调用。

首先是:

Configuration conf = new Configuration();

运行MapReduce程序前都要初始化Configuration,该类主要是读取MapReduce系统配置信息,这些信息包括hdfs还有MapReduce,也就是安装hadoop时候的配置文件例如:core-site.xml、hdfs-site.xml和mapred-site.xml等等文件里的信息,有些童鞋不理解为啥要这么做,这个是没有深入思考MapReduce计算框架造成,我们程序员开发MapReduce时候只是在填空,在map函数和reduce函数里编写实际进行的业务逻辑,其它的工作都是交给MapReduce框架自己操作的,但是至少我们要告诉它怎么操作啊,比如hdfs在哪里,MapReduce的jobstracker在哪里,而这些信息就在conf包下的配置文件里。

接下来的代码是:

    String[] otherArgs = new GenericOptionsParser(conf, args).getRemainingArgs();if (otherArgs.length != 2) {System.err.println("Usage: wordcount <in> <out>");System.exit(2);}

If的语句好理解,就是运行WordCount程序时候一定是两个参数,如果不是就会报错退出。至于第一句里的GenericOptionsParser类,它是用来解释常用hadoop命令,并根据需要为Configuration对象设置相应的值,其实平时开发里我们不太常用它,而是让类实现Tool接口,然后再main函数里使用ToolRunner运行程序,而ToolRunner内部会调用GenericOptionsParser。

接下来的代码是:

    Job job = new Job(conf, "word count");job.setJarByClass(WordCount.class);job.setMapperClass(TokenizerMapper.class);job.setCombinerClass(IntSumReducer.class);job.setReducerClass(IntSumReducer.class);

第一行就是在构建一个job,在mapreduce框架里一个mapreduce任务也叫mapreduce作业也叫做一个mapreduce的job,而具体的map和reduce运算就是task了,这里我们构建一个job,构建时候有两个参数,一个是conf这个就不累述了,一个是这个job的名称。

第二行就是装载程序员编写好的计算程序,例如我们的程序类名就是WordCount了。这里我要做下纠正,虽然我们编写mapreduce程序只需要实现map函数和reduce函数,但是实际开发我们要实现三个类,第三个类是为了配置mapreduce如何运行map和reduce函数,准确的说就是构建一个mapreduce能执行的job了,例如WordCount类。

第三行和第五行就是装载map函数和reduce函数实现类了,这里多了个第四行,这个是装载Combiner类,这个类和mapreduce运行机制有关,其实本例去掉第四行也没有关系,但是使用了第四行理论上运行效率会更好。

接下来的代码:

    job.setOutputKeyClass(Text.class);job.setOutputValueClass(IntWritable.class);

这个是定义输出的key/value的类型,也就是最终存储在hdfs上结果文件的key/value的类型。

最后的代码是:

    FileInputFormat.addInputPath(job, new Path(otherArgs[0]));FileOutputFormat.setOutputPath(job, new Path(otherArgs[1]));System.exit(job.waitForCompletion(true) ? 0 : 1);

第一行就是构建输入的数据文件,第二行是构建输出的数据文件,最后一行如果job运行成功了,我们的程序就会正常退出。

转载于:https://www.cnblogs.com/hehaiyang/p/4484442.html

相关文章:

cnblogs不愧为cnblogs

在cnblogs落脚3天了&#xff0c;写了一些很实践的文章&#xff0c;很有成就感&#xff0c;为什么&#xff1f;我第一次为是否发表这篇文章而作出思考&#xff0c;以前在别的地方&#xff0c;总是转别人的文章居多&#xff0c;到了cnblogs&#xff0c;感受到了原创的精神——即使…

Debian刊行版3晋级到4

作者: rincess 出自: http://www.linuxdiyf.com 前些天把供职器从Debian 3 sarge晋级到Debian 4 etch&#xff0c;经过议定考察这几天的运转浮现&#xff0c;感受非常满意。新的体系包孕了新的WWW供职器Apache 2.2和PHP 5.2.0&#xff0c;SVN也从1.1晋级到了1.4&#xff0c;Tr…

简单五子棋问题,java实现

**题目要求&#xff1a;**实现一个控制台下五子棋的程序。用一个二维数组模拟一个15*15路的五子棋棋盘&#xff0c;把每个元素赋值位“┼”可以画出棋盘&#xff0c; “○”代表该交叉点下了一颗白棋子&#xff0c;“●”代表该交叉点下了一颗黑棋子。每次用户输入要下棋的坐标…

Singleton 单例模板

1 // singleton.h2 3 #ifndef SINGLETON_H4 #define SINGLETON_H5 6 // 单例基类模板7 template <class T>8 class Singleton9 { 10 public: 11 static T& give_me() 12 { 13 static T s_inst; 14 return s_inst; 15 } 16 17 private: …

Oracle 7.3.4 for OpenServer 5 装配

起原&#xff1a;网海拾贝 1.建立oracle用户、dba组&#xff1b;2.调整系统中央参数&#xff1a;#./idtune SHMMAX 409600000#./idtune SEMMNI 153.装配SCO补丁文件 oss459A&#xff0c;重新毗连中央并重新启动&#xff1a;#/etc/conf/cf.d/link_unix -y#init 6   4.编纂oracl…

sql server中的hash应用优化

sql server很多地方用到hash&#xff0c;计划缓存查找&#xff0c;hash连接&#xff0c;hash聚合等。 hash查找mssql很多设计中都应用了&#xff0c;不过我们能在开发设计中&#xff0c;也可以利用这个特性。 将如果有需求对大文本进行完全匹配&#xff0c;比如查找产品型号&am…

JAVA猴子选大王问题

题目要求 猴子选大王。输入猴子的个数n&#xff0c;所有的猴子从1-n编号排成一圈&#xff0c;从1号猴子开始数数&#xff0c;数到3的倍数猴子被淘汰&#xff0c;最后剩下的是大王。输出是大王的猴子的编号&#xff08;提示&#xff1a;使用数组&#xff0c;每个数组元素相当于一…

POJ 1185 炮兵阵地 (状压DP)

炮兵阵地Time Limit: 2000MS Memory Limit: 65536KTotal Submissions: 14869 Accepted: 5575Description 司令部的将军们打算在N*M的网格地图上部署他们的炮兵部队。一个N*M的地图由N行M列组成&#xff0c;地图的每一格可能是山地&#xff08;用"H" 表示&#xff09;…

不雅测发挥分析Android在美智能机市场凌驾黑莓及苹果

网易科技讯 3月4日动静&#xff0c;根据尼尔森公司比来宣布的陈诉发挥分析&#xff0c;Android操纵体系以29%的市占率在美国智好手机市场凌驾黑莓(27%)和苹果(27%)。其中&#xff0c;宏达电占12%&#xff0c;摩托罗拉占10%&#xff0c;三星占5%。但从厂商角度来看&#xff0c;苹…

Java基础-常量,变量,成员变量,局部变量

在java中&#xff0c;数据是以常量和变量两种方法形式进行存储和表示的&#xff08;实际上&#xff0c;所有程序的数据都是这两种形式&#xff09;。 变量 变量代表程序的状态。程序通过改变变量的值来改变整个程序的状态&#xff0c;或者说得更大一些&#xff0c;也就是实现程…

把eclipse从英文调整为中文

鼠标右键单击桌面上的快捷方式&#xff0c;选择文件所在位置 选择配置设置 eclipse.ini 在最后加上 -Duser.languageen 然后重启eclipse即可

关系数据理论中的范式

标准化表示从你的数据存储中移去数据冗余(redundancy)的过程。如果数据库设计达到了完全的标准化&#xff0c;则把所有的表通过关键字连接在一起时&#xff0c;不会出现任何数据的复本(repetition)。标准化的优点是明显的&#xff0c;它避免了数据冗余&#xff0c;自然就节省了…

无法在证书存储区中找到清单签名证书的解决办法

以前的一个项目今天打开忽然提示说“无法在证书存储区中找到清单签名证书”&#xff0c;很郁闷&#xff0c;不知道怎么回事。最好在 工程属性里面&#xff0d;&#xff0d;签名&#xff0d;&#xff0d;为Clickonce清单签名 去掉 。再次生成居然成功了。不知道具体什么原因引起…

Linux Centos 上一些常用的命令

1、查看端口被哪个进程占用 netstat -lnp | grep <端口号> 2、查看某个进程号详细信息 ps <进程号> 3、检查指定服务是否开启&#xff08;例如 telnet&#xff09; chkconfig --list | grep telnet chkconfig iptables on &#xff08;打开某个服务器自启动&#…

eclipse提示在***类中找不到main方法

可能是因为注释加的太多了&#xff0c;在代码最开始的时候 这时候&#xff0c;把注释删掉就可以了 就像这样&#xff0c;这时候不要惊慌&#xff0c;先看一下是不是注释太多了&#xff0c;如果不是的话&#xff0c;请百度搜索解决办法

【随记】动态调用web服务

通常我们在程序中需要调用WebService时&#xff0c;都是通过“添加Web引用”&#xff0c;让VS.NET环境来为我们生成服务代理&#xff0c;然后调用对应的Web服务。这样是使工作简单了&#xff0c;但是却和提供Web服务的URL、方法名、参数绑定在一起了&#xff0c;这是VS.NET自动…

在博客中加入“花絮”效果

在博客中加入Snap Shots Snap Shots表示“花絮”的意思&#xff0c;在博客中可以使用Snap Shots来添加“花絮”效果。先演示一遍效果&#xff0c;看是否能用&#xff1a;http://www.cnblogs.com/psunny内部的链接Snap Shots效果不可用 http://www.google.cn外部的链接Snap Shot…

phonegap调用摄像头

phonegap的HTML5的代码 是通用的 自己写了个 可是发现 在安卓机上市可以实现拍照的 但是iOS上却不行 这是为什么 我一直不解 document.addEventListener("deviceready", onDeviceReady, false); function onDeviceReady() { document.addEventListener(&quo…

关于JDBC中的 PreparedStatement 的使用讲解

**关于JDBC中的 PreparedStatement 的使用讲解**TOC 文章转载于博客 https://www.cnblogs.com/ysw-go/p/5459330.html 如有侵权&#xff0c;联系删除

SQLite数据转换成sql server数据

需要将SQLite数据库里的数据导入到SQL Server&#xff0c;在网上搜了好久&#xff0c;没有找到一个方便实用的方法。 经过本人的细心琢磨实验&#xff0c;终于让我给找到一好的方法&#xff1a;使用CSV文件作为介质来做转换。现在记录下来&#xff0c;一是小小庆祝一下&#xf…

Animation Override Controller动画重载器

假设游戏有很多个小人, 每一个人有2种动画站立,跑. 在通常情况下每一个人物都需要一个动画控制器。 有没有想过定义一个动画控制器 无须在定义全新的动画充值器实现每一个小人都播放自己的动画呢&#xff1f;没错Animation Oveeride Controller就是来解决这个问题的 1. 我们设…

java连接mysql8的坑

变化&#xff1a; 1.Class.forName(“com.mysql.cj.jdbc.Driver”); 2.connDriverManager.getConnection(“jdbc:mysql://localhost/数据库名字?serverTimezoneUTC”,“root”,“密码”); package chap01;import java.sql.Connection; import java.sql.DriverManager; import…

Oracle用户管理

创建用户create user–概述&#xff1a;在oracle中要创建一个新的用户使用 create user 语句,一般是具有dba(数据库管理员)的权限才能使用。–基本语法&#xff1a;create user 用户名 identified by 密码create user dbuser1 identified by dbuser1; 用户赋权grant–概述&…

UNIX网络编程--ioctl操作(十七)

一、概述 在本书中有两个地方都对这个函数进行了介绍&#xff0c;其实还有很多地方需要这个函数。ioclt函数传统上一直作为纳西而不适合归入其他精细定义类别的特性的系统接口。网络程序&#xff08;特别是服务器程序&#xff09;经常在程序启动执行后使用ioctl获取所在主机全部…

Servlert接口的doGet()、doPst()方法

Serlvet接口只定义了一个服务方法就是service&#xff0c;而HttpServlet类实现了该方法并且要求调用下列的方法之一&#xff1a; doGet&#xff1a;处理GET请求 doPost&#xff1a;处理POST请求 当发出客户端请求的时候&#xff0c;调用service 方法并传递一个请求和响应对象&a…

Web服务器 之 Apache 2.x 服务器中的URL重写的配置和应用

作者&#xff1a;北南南北来自&#xff1a;LinuxSir.Org摘要&#xff1a; 本文是关于Apache 2.x 服务器中的URL别名规则的文档&#xff0c;它是通过rewrite模块来实现的。能过URL别名规则&#xff0c;我们能看到一个干净的URL&#xff0c;比如可以重写为类似静态网页的地址。比…

杜拉拉的作者李可应北大就业指导中心之约写给大学生的一封信

本文是杜拉拉的作者李可应北大就业指导中心之约写给大学生的一封信。 北大的同学们&#xff0c;大家好&#xff1a;又到了临近毕业的日子&#xff0c;年复一年&#xff0c;在这个梦想周期性遭遇现实的季节&#xff0c;对一代又一代的莘莘学子而言&#xff0c;在精神上和身体上准…

VLC架构及流程分析

0x00 前置信息 VLC是一个非常庞大的工程&#xff0c;我从它的架构及流程入手进行分析&#xff0c;涉及到一些很细的概念先搁置一边&#xff0c;日后详细分析。 0x01 源码结构&#xff08;Android Java相关的暂未分析&#xff09; # build-android-arm-linux-androideabi/&#…

eclipse运行程序时只有run on server

最近写jsp的程序比较多&#xff0c;写java程序时&#xff0c;发现一点击运行按钮就开始启动服务器了&#xff0c; 这是因为没有写主函数的原因 注意这个问题

自动生成小学四则运算题目的程序.心得体会

http://t.cn/RAS67B0 源代码 #include<stdio.h> #include<stdlib.h>#include<time.h>main(){int a,b,op,os; printf(" [天天练&#xff0c;Baby们来挑战吧!]\n");aq1: printf("选择您想挑战的运算法则\n");printf("1.加法 2.减法 3…