MapReduce Prgramming实验
Source Code for WordCount v1.0
From http://hadoop.apache.org/docs/stable/mapred_tutorial.html#Source+Code
WordCount.java
- package org.myorg;
- import java.io.IOException;
- import java.util.*;
- import org.apache.hadoop.fs.Path;
- import org.apache.hadoop.conf.*;
- import org.apache.hadoop.io.*;
- import org.apache.hadoop.mapred.*;
- import org.apache.hadoop.util.*;
- public class WordCount {
- public static class Map extends MapReduceBase implements Mapper<LongWritable, Text, Text, IntWritable> {
-
private final static IntWritable one = new IntWritable(1);
-
private Text word = new Text();
-
public void map(LongWritable key, Text value, OutputCollector<Text, IntWritable> output, Reporter reporter) throws IOException {
-
String line = value.toString();
-
StringTokenizer tokenizer = new StringTokenizer(line);
-
while (tokenizer.hasMoreTokens()) {
-
word.set(tokenizer.nextToken());
-
output.collect(word, one);
-
}
-
}
- }
- public static class Reduce extends MapReduceBase implements Reducer<Text, IntWritable, Text, IntWritable> {
-
public void reduce(Text key, Iterator<IntWritable> values, OutputCollector<Text, IntWritable> output, Reporter reporter) throws IOException {
2
30. int sum = 0;
31. while (values.hasNext()) {
32. sum += values.next().get();
33. }
34. output.collect(key, new IntWritable(sum));
35. }
36. }
37.
38. public static void main(String[] args) throws Exception {
39. JobConf conf = new JobConf(WordCount.class);
40. conf.setJobName(“wordcount”);
41.
42. conf.setOutputKeyClass(Text.class);
43. conf.setOutputValueClass(IntWritable.class);
44.
45. conf.setMapperClass(Map.class);
46. conf.setCombinerClass(Reduce.class);
47. conf.setReducerClass(Reduce.class);
48.
49. conf.setInputFormat(TextInputFormat.class);
50. conf.setOutputFormat(TextOutputFormat.class);
51.
52. FileInputFormat.setInputPaths(conf, new Path(args[0]));
53. FileOutputFormat.setOutputPath(conf, new Path(args[1]));
54.
55. JobClient.runJob(conf);
56. }
57. }
演练
WordCount应用程序非常简单。
Mapper实现(第14-26行)通过map方法(第18-25行)一次处理一行,这是由指定的TextInputFormat(第49行)提供的。然后,它通过StringTokenizer将行分割成由空白分隔的令牌,并发出一对键值
< , 1>.
对于给定的示例输入,第一个映射发出:
< Hello, 1>
< World, 1>
< Bye, 1>
< World, 1>
第二个map发出:
< Hello, 1>
< Hadoop, 1>
< Goodbye, 1>
< Hadoop, 1>
在本教程稍后的部分中,我们将了解为给定作业生成的映射的数量,以及如何以细粒度的方式控制它们。
WordCount还指定了一个组合器(第46行)。因此,在对键进行排序之后,每个映射的输出将通过本地组合器(根据作业配置,与Reducer相同)进行本地聚合。
第一个map的输出:
< Bye, 1>
< Hello, 1>
< World, 2>
第二个map的输出:
< Goodbye, 1>
< Hadoop, 2>
< Hello, 1>
Reducer实现(第28-36行)通过reduce方法(第29-35行)总结了值,这些值是每个键(即本例中的单词)的出现计数。
因此作业的输出为:
< Bye, 1>
< Goodbye, 1>
< Hadoop, 2>
< Hello, 2>
< World, 2>
run方法指定作业的各个方面,例如JobConf中的输入/输出路径(通过命令行传递)、键/值类型、输入/输出格式等。然后它调用JobClient.runJob(第55行)来提交和监视其进度。
一些关于WordCount程序的评论
Chuck Lam的Hadoop in Action (Greenwich, CT: Manning Publications, 2011)在第13-14页中给出了WordCount的伪代码
要分布在许多机器上的第一阶段的伪代码是
define wordCount as Multiset;
for each document in documentSubset {
T = tokenize(document);
for each token in T {
wordCount[token]++;
}
}
sendToSecondPhase(wordCount);
第二阶段的伪代码是
define totalWordCount as Multiset;
for each wordCount received from firstPhase {
multisetAdd (totalWordCount, wordCount);
}
在第17-18页的WordCount程序中,该书还建议进行以下改进
我们想对程序做的更改很容易发现。我们看到WordCount在其默认设置中使用Java的StringTokenizer,该设置仅基于空白进行标记。为了忽略标准标点符号,我们将它们添加到StringTokenizer的分隔符字符列表中:
StringTokenizer itr = new StringTokenizer(line, " \t\n\r\f,.:;?![]’");
在遍历标记集时,提取每个标记并将其转换为文本对象。(同样,在Hadoop中,使用特殊的类文本代替字符串)。我们希望单词计数忽略大写,因此在将它们转换为Textobjects之前,我们将所有单词都小写。
word.set(itr.nextToken().toLowerCase());
我们修改以仅在满足该条件时才将单词计数收集到输出中。(这是Hadoop中的emit()函数,相当于伪代码中的emit()函数)。)
if (sum > 4) output.collect(key, new IntWritable(sum));
Exercise 1 MapReduce using the Java Perspective
使用JAVA透视图MAPREDUCE
1.1开始BIGINSIGHTS组件在ECLIPSE
1.2定义了一个JAVA项目
1.3创建一个JAVA包MAPPER类
1.4完成MAPPER
1.5创建类减速器
1.6完成减速器
1.7创建驱动程序
1.8创建一个JAR文件
1.9添加组合器函数
1.10重新创建JAR文件
1.11再次运行您的应用程序
lab1 Mapreduce使用Java透视图
在这个练习中,学生开发了一个MapReduce应用程序,该应用程序使用Eclipse中的Java透视图查找最高的月平均温度。
完成这个动手实验后,你将能够:
•在Eclipse中使用Java透视图编写MapReduce应用程序
给这个实验室45分钟。
这个版本的实验室是使用InfoSphere BigInsights 2.1快速启动版设计的,但已经在3.0映像上进行了测试。在整个实验过程中,您将使用以下帐户登录信息。如果您的密码不同,请注意差异。
假设您已经按照本课程的指导下载并解压缩了BDU_Hadoop_Files.tar. 文件。这个练习需要tar文件中的数据。
1.1启动BigInsights组件
__ 1。使用biadmin的用户id和密码登录到BigInsights映像。
__ 2。启动BigInsights组件。使用桌面上的图标。
__ 3。从命令行(右键单击桌面并选择Open in Terminal)执行:
hadoop fs -mkdir TempData
__ 4。从本地文件系统上传一些温度数据。
hadoop fs -copyFromLocal /home/labfiles/SumnerCountyTemp.dat /user/biadmin/TempData
__5。您可以从Web控制台的Files选项卡或通过执行以下命令查看此数据。第95列的值(354,353,353,353,352…)是平均每日温度。它们是实际平均值的乘积温度值乘以10。(这样你就不用担心小数点的问题了)
hadoop fs -cat TempData/SumnerCountyTemp.dat
1.2在Eclipse 中定义Java项目
__ 1。使用桌面上的图标启动Eclipse。使用默认工作区。
__ 2。确保您正在使用Java透视图。点击 Window->Open Perspective>Other.。然后选择Java。单击OK。
__ 3。创建一个Java项目。选择File->New->Java Project. 。
__ 4。指定项目名称MaxTemp。单击Finish。
__ 5。右键单击MaxTemp项目,向下滚动并选择Properties。
__ 6。选择 Java Build Path
__ 7。在“属性”对话框中,选择Libraries 选项卡。
__ 8。单击Add Library按钮。
__ 9。选择BigInsights Libraries 并单击Next。然后单击Finish。然后单击OK。
1.3创建Java包和mapper类
__ 1。在Package Explorer中展开MaxTemp并右键单击src。选择New->Package。
__ 2。键入com.some.company的名称。单击Finish。
__ 3。右键单击com.some.company并选择New->Class。
__ 4。输入MaxTempMapper的名称。它将是一个公共类。单击Finish。
mapper的输入键的数据类型是LongWritable。数据本身将是文本类型。mapper的输出键类型为Text。来自制图器的数据(温度)将是IntWritable的类型。
__ 5。你的类:
__ a.你需要导入java.io.IOException。
__ b. Exend Mapper<LongWritable, Text, Text, IntWritable>
__ c.定义一个名为map的公共类。
你的代码应该看起来像这样:
package com.some.company;
import java.io.IOException;
import org.apache.hadoop.io.IntWritable;
import org.apache.hadoop.io.LongWritable;
import org.apache.hadoop.io.Text;
import org.apache.hadoop.mapreduce.Mapper;
public class MaxTempMapper extends
Mapper<LongWritable, Text, Text, IntWritable> {
@Override public void map(LongWritable key, Text value, Context context)
throws IOException, InterruptedException {
}
}
1.4完成映射器
在一行数据中正在读取的。您将希望将其转换为字符串,以便进行一些字符串操作。您需要提取每个记录的月份和平均温度。
月份从记录的第22个字符(零偏移量)开始,平均温度从第95个字符开始。(记住,平均温度值是三位数。)
__ 1。在map方法中,添加以下代码(或者您认为需要的任何代码):
String line = value.toString();
String month = line.substring(22,24);
int avgTemp;
avgTemp = Integer.parseInt(line.substring(95,98));
context.write(new Text(month), new IntWritable(avgTemp));
__ 2。保存您的工作。
1.5创建reducer类
__ 1。在包资源管理器中右键单击com.some.company并选择New->类。
__ 2。输入MaxTempReducer的名称。它将是一个公共类。单击Finish。
还原程序的输入键的数据类型将是文本。数据本身的类型为IntWritable。减速机的输出键为文本类型。而来自减速器的数据将是IntWritable的类型。
__ 3。你的类:
__ a.您需要导入java.io.IOException。
__ b. Extend Reducer<Text, LongWritable, Text, IntWritable>
__c.定义一个名为reduce的公共类。
__ d.您的代码应该如下所示:
package com.some.company;
import java.io.IOException;
import org.apache.hadoop.io.IntWritable;
import org.apache.hadoop.io.Text;
import org.apache.hadoop.mapreduce.Reducer;
public class MaxTempReducer extends
Reducer<Text, IntWritable, Text, IntWritable> {
@Override
public void reduce(Text key, Iterable values, Context context)
throws IOException, InterruptedException { }
}
1.6完成reducer
对于简化程序,您希望遍历给定键的所有值。对于每个值,检查它是否高于其他任何值。
__ 1。将以下代码(或您的变体)添加到reduce方法中。
int maxTemp = Integer.MIN_VALUE;
for (IntWritable value: values) {
maxTemp = Math.max(maxTemp, value.get());
}
context.write(key, new IntWritable(maxTemp));
__ 2。保存您的工作。
1.7创建驱动程序
__ 1。在包资源管理器中右键单击com.some.company并选择New->类。
__ 2。输入MaxMonthTemp的名称。它将是一个公共类。单击Finish。
GenericOptionsParser()将提取任何不是系统参数的输入参数,并将它们放在一个数组中。在您的示例中,将向应用程序传递两个参数。第一个参数是输入文件。第二个参数是输出目录。(此目录必须不存在,否则MapReduce应用程序将失败。)你的代码应该是这样的:
package com.some.company;
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.lib.input.FileInputFormat;
import org.apache.hadoop.mapreduce.lib.output.FileOutputFormat;
import org.apache.hadoop.util.GenericOptionsParser;
import com.some.company.MaxTempReducer;
import com.some.company.MaxTempMapper;
public class MaxMonthTemp {
public static void main(String[] args) throws Exception {
Configuration conf = new Configuration();
String[] programArgs = new GenericOptionsParser(conf, args).getRemainingArgs();
if (programArgs.length != 2) {
System.err.println("Usage: MaxTemp <in> <out>");
System.exit(2);
}
Job job = new Job(conf, "Monthly Max Temp");
job.setJarByClass(MaxMonthTemp.class);
job.setMapperClass(MaxTempMapper.class);
job.setReducerClass(MaxTempReducer.class);
job.setOutputKeyClass(Text.class);
job.setOutputValueClass(IntWritable.class);
FileInputFormat.addInputPath(job, new Path(programArgs[0]));
FileOutputFormat.setOutputPath(job, new Path(programArgs[1]));
// Submit the job and wait for it to finish.
System.exit(job.waitForCompletion(true) ? 0 : 1);
} }
__3.保存你的工作
1.8创建JAR文件
__ 1。在Package Explorer中,展开MaxTemp项目。右键单击src并选择Export。
__ 2。展开Java并选择JAR文件。单击Next。
__ 3。单击JAR文件浏览按钮。输入MyMaxTemp.jar的名称。保存biadmin作为文件夹。单击OK。
__ 4。单击Finish。
为了节省时间,现在不运行应用程序。您将添加一个combiner类,然后运行应用程序。
1.9添加组合函数
__ 1。返回Eclipse开发环境。您将向应用程序中添加一个组合函数。在实际的多节点集群中,这将允许在mapper节点上执行一些减少功能,并减少网络流量。
__ 2。查看MaxMonthTemp.java的代码。在job.setMaperClass(MaxTempMapper.class)之后添加以下语句;声明。
job.setCombinerClass(MaxTempReducer.class);
__ 3。保存您的工作。
1.10重新创建JAR文件
__ 1。在Project Explorer中展开MaxTemp项目。右键单击src并选择Export。
__ 2。展开Java并选择JAR文件。单击Next。
__ 3。单击JAR文件browse 按钮。输入MyMaxTemp.jar的名称。保存biadmin作为文件夹。单击OK。
__ 4。单击Finish。覆盖并替换上一个JAR。
1.11运行应用程序
__ 1。您需要一个命令行。你可能得再开一个。切换到biadmin的主目录。
cd ~
__ 2。执行程序。命令行输入:
hadoop jar MyMaxTemp.jar com.some.company.MaxMonthTemp /user/biadmin/TempData/SumnerCountyTemp.dat /user/biadmin/TempDataOut
__ 3。关闭Eclipse中打开的编辑窗口。
Exercise 2 MapReduce using the BigInsights Perspective
lab1 Mapreduce使用BigInsights透视图
在本练习中,学生将使用BigInsights Eclipse开发环境中的MapReduce向导为应用程序创建基础。然后学生可以比较使用开发环境的好处。
完成这个动手实验后,你将能够:
•使用BigInsights Eclipse MapReduce向导生成MapReduce模板
给这个实验室45分钟。
这个版本的实验室是使用InfoSphere BigInsights 2.1快速启动版设计的,但已经在3.0映像上进行了测试。在整个实验过程中,您将使用以下帐户登录信息。如果您的密码不同,请注意差异。
您刚刚经历了创建MapReduce应用程序的过程。因为提供了代码,所以相对容易。但是,如果该练习只指定编写MapReduce应用程序呢?就是这样。不提供代码。你会从哪里开始?在练习的这一部分中,您将使用BigInsights开发环境开始这项工作。
1.1创建MapReduce模板
__ 1。如果您关闭了Eclipse,那么通过双击桌面上的Eclipse图标来启动Eclipse。当需要工作区时,单击OK。
__ 2。选择BigInsights文本分析工作流透视图。在菜单栏中,选择Window->Open Perspective->Other。选择BigInsights并单击OK。
__ 3。如果BigInsights任务启动器不再打开,点击 Help->Task launcher for Big Data.
__ 4。在BigInsights任务启动器中,应该选择Overview选项卡。单击 Create a new BigInsights project.
__ 5。输入一个名为BIMaxTemp的项目名称。单击Finish。(你可以关闭帮助选项卡)
__ 6。在BigInsights任务启动器中,单击Develop 选项卡。
__ 7。选择 Create a BigInsights program.
__ 8。单击 Java MapReduce Program radiobutton,然后单击OK。(这将完成与右键单击MaxTemp->New->Other相同的事情。)然后在BigInsights下,选择Java MapReduce Program)。
__ 9。为mapper类指定模板信息。对于源文件夹,单击Browse按钮,展开BIMaxTemp,选择src,然后单击OK。
__ 10。键入com.ibm的包。
__ 11。对于名称,输入MaxTempMapper。
mapper的输入键的数据类型是LongWritable。数据本身将是文本类型。mapper的输出键类型为Text。来自制图器的数据(温度)将是IntWritable的类型。
__ 12。对于输入键的类型,选择Browse按钮。在LongWritable类型。在显示的列表中,选择LongWritable- org.apache.hadoop.io。单击OK。
__ 13。对于输入值的类型,选择Browse按钮。输入Text 。在显示的列表中,选择Text - org.apache.hadoop.io。单击OK。
__ 14。对于输出键的类型,选择Browse按钮。在匹配项列表中选择Text 。单击OK。
__ 15。对于输出值的类型,选择Browse按钮。在IntWritable类型。在显示的列表中,选择IntWritable- org.apache.hadoop.io。单击OK。
__ 16。单击Next。
__ 17。现在,为reducer类指定模板信息。要获得reducer类的名称,输入MaxTempReducer。
__ 18。对于输出键的类型,选择Browse按钮。选择显示列表中的文本。单击OK。
__ 19。对于输出值的类型,选择Browse按钮。在显示的列表中选择IntWritable,选择IntWritable- org.apache.hadoop.io。单击OK。
__ 20。单击Next。
__ 21。最后为驱动程序指定模板信息。对于主类,输入一个com.ibm包。
__ 22。对于名称类型MaxMonthlyTemp。然后单击Finish。
__ 23。查看生成的三个Java类的代码。您所需要做的就是添加特定于MapReduce应用程序的代码。您可以看到,使用这个BigInsights向导,极大地简化了生成MapReduce应用程序。为了加快速度,您实际上不需要向这些模板添加任何代码。我只是想让你们看到使用BigInsights的好处。
__ 24。关闭打开的编辑窗口。然后关闭Eclipse。
__ 25。双击桌面上的Stop BigInsights图标,停止BigInsights组件。