用Java编写Hadoop MapReduce任务

尽管Hadoop框架本身是使用Java创建的,但MapReduce作业可以用许多不同的语言编写。 在本文中,我将展示如何像其他Java项目一样,基于Maven项目在Java中创建MapReduce作业。

    • 准备示例输入

让我们从一个虚构的商业案例开始。 在这种情况下,我们需要一个CSV文件,其中包含字典中的英语单词,并添加了其他语言的所有翻译,并以'|'分隔 符号。 我已经根据这篇文章给出了这个例子。 因此,这项工作将阅读不同语言的词典,并将每个英语单词与另一种语言的翻译匹配。 作业的输入字典是从此处获取的 。 我下载了几种不同语言的文件,并将它们放到一个文件中(Hadoop处理多个大文件比处理多个小文件更好)。 我的示例文件可以在这里找到。

    • 创建Java MapReduce项目

下一步是为MapReduce作业创建Java代码。 就像我在使用Maven项目之前所说的那样,所以我在自己的IDE IntelliJ中创建了一个新的空Maven项目。 我修改了默认pom以添加必要的插件和依赖项:
我添加的依赖项:

<dependency><groupId>org.apache.hadoop</groupId><artifactId>hadoop-core</artifactId><version>1.2.0</version><scope>provided</scope>
</dependency>

Hadoop依赖关系对于使用MapReduce作业中的Hadoop类是必需的。 由于我想在AWS EMR上运行作业,因此请确保我具有匹配的Hadoop版本。 此外,由于Hadoop框架将在Hadoop群集上可用,因此可以将范围设置为“已提供”。

除了依赖关系之外,我还在pom.xml中添加了以下两个插件:

<plugins><plugin><groupId>org.apache.maven.plugins</groupId><artifactId>maven-jar-plugin</artifactId><configuration><archive><manifest><addClasspath>true</addClasspath><mainClass>net.pascalalma.hadoop.Dictionary</mainClass></manifest></archive></configuration></plugin><plugin><groupId>org.apache.maven.plugins</groupId><artifactId>maven-compiler-plugin</artifactId><configuration><source>1.6</source><target>1.6</target></configuration></plugin>
</plugins>

第一个插件用于创建我们项目的可执行jar。 这使JAR在Hadoop集群上的运行更加容易,因为我们不必声明主类。

为了使创建的JAR与AWS EMR集群的实例兼容,第二个插件是必需的。 该AWS集群随附JDK 1.6。 如果您忽略此选项,则群集将失败(我收到类似“不支持的major.minor版本51.0”之类的消息)。 稍后,我将在另一篇文章中介绍如何设置此AWS EMR集群。

这是基本项目,就像常规的Java项目一样。 接下来让我们实现MapReduce作业。

    • 实现MapReduce类

我已经描述了我们要在第一步中执行的功能。 为此,我在Hadoop项目中创建了三个Java类。 第一类是“ Mapper ”:

package net.pascalalma.hadoop;import org.apache.hadoop.io.Text;
import org.apache.hadoop.mapreduce.Mapper;import java.io.IOException;
import java.util.StringTokenizer;/*** Created with IntelliJ IDEA.* User: pascal* Date: 16-07-13* Time: 12:07*/
public class WordMapper extends Mapper<Text,Text,Text,Text> {private Text word = new Text();public void map(Text key, Text value, Context context) throws IOException, InterruptedException{StringTokenizer itr = new StringTokenizer(value.toString(),",");while (itr.hasMoreTokens()){word.set(itr.nextToken());context.write(key, word);}}
}

这个课不是很复杂。 它只是从输入文件中接收一行,并为其创建一个Map,该映射中的每个键都有一个值(在此阶段允许多个键)。

下一类是“ Reducer ”,它将地图缩小为所需的输出:

package net.pascalalma.hadoop;import org.apache.hadoop.io.Text;
import org.apache.hadoop.mapreduce.Reducer;import java.io.IOException;/*** Created with IntelliJ IDEA.* User: pascal* Date: 17-07-13* Time: 19:50*/
public class AllTranslationsReducer extends Reducer<Text, Text, Text, Text> {private Text result = new Text();@Overrideprotected void reduce(Text key, Iterable<Text> values, Context context) throws IOException, InterruptedException {String translations = "";for (Text val : values) {translations += "|" + val.toString();}result.set(translations);context.write(key, result);}
}

减少步骤将收集给定键的所有值,并将它们彼此之间用“ |”分隔 符号。

剩下的最后一堂课是将所有内容放在一起以使其可运行的工作:

package net.pascalalma.hadoop;import org.apache.hadoop.conf.Configuration;
import org.apache.hadoop.fs.Path;
import org.apache.hadoop.io.Text;import org.apache.hadoop.mapreduce.lib.input.KeyValueTextInputFormat;
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.mapreduce.lib.output.TextOutputFormat;/*** Created with IntelliJ IDEA.* User: pascal* Date: 16-07-13* Time: 12:07*/
public class Dictionary {public static void main(String[] args) throws Exception{Configuration conf = new Configuration();Job job = new Job(conf, "dictionary");job.setJarByClass(Dictionary.class);job.setMapperClass(WordMapper.class);job.setReducerClass(AllTranslationsReducer.class);job.setOutputKeyClass(Text.class);job.setOutputValueClass(Text.class);job.setMapOutputKeyClass(Text.class);job.setMapOutputValueClass(Text.class);job.setInputFormatClass(KeyValueTextInputFormat.class);job.setOutputFormatClass(TextOutputFormat.class);FileInputFormat.addInputPath(job, new Path(args[0])); FileOutputFormat.setOutputPath(job, new Path(args[1]));boolean result = job.waitForCompletion(true);System.exit(result ? 0 : 1);}
}

在这种主要方法中,我们将一个Job放在一起并运行它。 请注意,我只是希望args [0]和args [1]是输入文件和输出目录的名称(不存在)。 我没有为此添加任何检查。 这是我在IntelliJ中的“运行配置”:

屏幕截图-2013-08-15-at-21-36-35

只需确保在运行类时输出目录不存在。 作业创建的日志记录输出如下所示:

2013-08-15 21:37:00.595 java[73982:1c03] Unable to load realm info from SCDynamicStore
aug 15, 2013 9:37:01 PM org.apache.hadoop.util.NativeCodeLoader <clinit>
WARNING: Unable to load native-hadoop library for your platform... using builtin-java classes where applicable
aug 15, 2013 9:37:01 PM org.apache.hadoop.mapred.JobClient copyAndConfigureFiles
WARNING: Use GenericOptionsParser for parsing the arguments. Applications should implement Tool for the same.
aug 15, 2013 9:37:01 PM org.apache.hadoop.mapred.JobClient copyAndConfigureFiles
WARNING: No job jar file set.  User classes may not be found. See JobConf(Class) or JobConf#setJar(String).
aug 15, 2013 9:37:01 PM org.apache.hadoop.mapreduce.lib.input.FileInputFormat listStatus
INFO: Total input paths to process : 1
aug 15, 2013 9:37:01 PM org.apache.hadoop.io.compress.snappy.LoadSnappy <clinit>
WARNING: Snappy native library not loaded
aug 15, 2013 9:37:01 PM org.apache.hadoop.mapred.JobClient monitorAndPrintJob
INFO: Running job: job_local_0001
aug 15, 2013 9:37:01 PM org.apache.hadoop.mapred.Task initialize
INFO:  Using ResourceCalculatorPlugin : null
aug 15, 2013 9:37:01 PM org.apache.hadoop.mapred.MapTask$MapOutputBuffer <init>
INFO: io.sort.mb = 100
aug 15, 2013 9:37:01 PM org.apache.hadoop.mapred.MapTask$MapOutputBuffer <init>
INFO: data buffer = 79691776/99614720
aug 15, 2013 9:37:01 PM org.apache.hadoop.mapred.MapTask$MapOutputBuffer <init>
INFO: record buffer = 262144/327680
aug 15, 2013 9:37:02 PM org.apache.hadoop.mapred.MapTask$MapOutputBuffer flush
INFO: Starting flush of map output
aug 15, 2013 9:37:02 PM org.apache.hadoop.mapred.MapTask$MapOutputBuffer sortAndSpill
INFO: Finished spill 0
aug 15, 2013 9:37:02 PM org.apache.hadoop.mapred.Task done
INFO: Task:attempt_local_0001_m_000000_0 is done. And is in the process of commiting
aug 15, 2013 9:37:02 PM org.apache.hadoop.mapred.JobClient monitorAndPrintJob
INFO:  map 0% reduce 0%
aug 15, 2013 9:37:04 PM org.apache.hadoop.mapred.LocalJobRunner$Job statusUpdate
INFO: 
aug 15, 2013 9:37:04 PM org.apache.hadoop.mapred.Task sendDone
INFO: Task 'attempt_local_0001_m_000000_0' done.
aug 15, 2013 9:37:04 PM org.apache.hadoop.mapred.Task initialize
INFO:  Using ResourceCalculatorPlugin : null
aug 15, 2013 9:37:04 PM org.apache.hadoop.mapred.LocalJobRunner$Job statusUpdate
INFO: 
aug 15, 2013 9:37:04 PM org.apache.hadoop.mapred.Merger$MergeQueue merge
INFO: Merging 1 sorted segments
aug 15, 2013 9:37:04 PM org.apache.hadoop.mapred.Merger$MergeQueue merge
INFO: Down to the last merge-pass, with 1 segments left of total size: 524410 bytes
aug 15, 2013 9:37:04 PM org.apache.hadoop.mapred.LocalJobRunner$Job statusUpdate
INFO: 
aug 15, 2013 9:37:05 PM org.apache.hadoop.mapred.Task done
INFO: Task:attempt_local_0001_r_000000_0 is done. And is in the process of commiting
aug 15, 2013 9:37:05 PM org.apache.hadoop.mapred.LocalJobRunner$Job statusUpdate
INFO: 
aug 15, 2013 9:37:05 PM org.apache.hadoop.mapred.Task commit
INFO: Task attempt_local_0001_r_000000_0 is allowed to commit now
aug 15, 2013 9:37:05 PM org.apache.hadoop.mapreduce.lib.output.FileOutputCommitter commitTask
INFO: Saved output of task 'attempt_local_0001_r_000000_0' to /Users/pascal/output
aug 15, 2013 9:37:05 PM org.apache.hadoop.mapred.JobClient monitorAndPrintJob
INFO:  map 100% reduce 0%
aug 15, 2013 9:37:07 PM org.apache.hadoop.mapred.LocalJobRunner$Job statusUpdate
INFO: reduce > reduce
aug 15, 2013 9:37:07 PM org.apache.hadoop.mapred.Task sendDone
INFO: Task 'attempt_local_0001_r_000000_0' done.
aug 15, 2013 9:37:08 PM org.apache.hadoop.mapred.JobClient monitorAndPrintJob
INFO:  map 100% reduce 100%
aug 15, 2013 9:37:08 PM org.apache.hadoop.mapred.JobClient monitorAndPrintJob
INFO: Job complete: job_local_0001
aug 15, 2013 9:37:08 PM org.apache.hadoop.mapred.Counters log
INFO: Counters: 17
aug 15, 2013 9:37:08 PM org.apache.hadoop.mapred.Counters log
INFO:   File Output Format Counters 
aug 15, 2013 9:37:08 PM org.apache.hadoop.mapred.Counters log
INFO:     Bytes Written=423039
aug 15, 2013 9:37:08 PM org.apache.hadoop.mapred.Counters log
INFO:   FileSystemCounters
aug 15, 2013 9:37:08 PM org.apache.hadoop.mapred.Counters log
INFO:     FILE_BYTES_READ=1464626
aug 15, 2013 9:37:08 PM org.apache.hadoop.mapred.Counters log
INFO:     FILE_BYTES_WRITTEN=1537251
aug 15, 2013 9:37:08 PM org.apache.hadoop.mapred.Counters log
INFO:   File Input Format Counters 
aug 15, 2013 9:37:08 PM org.apache.hadoop.mapred.Counters log
INFO:     Bytes Read=469941
aug 15, 2013 9:37:08 PM org.apache.hadoop.mapred.Counters log
INFO:   Map-Reduce Framework
aug 15, 2013 9:37:08 PM org.apache.hadoop.mapred.Counters log
INFO:     Reduce input groups=11820
aug 15, 2013 9:37:08 PM org.apache.hadoop.mapred.Counters log
INFO:     Map output materialized bytes=524414
aug 15, 2013 9:37:08 PM org.apache.hadoop.mapred.Counters log
INFO:     Combine output records=0
aug 15, 2013 9:37:08 PM org.apache.hadoop.mapred.Counters log
INFO:     Map input records=20487
aug 15, 2013 9:37:08 PM org.apache.hadoop.mapred.Counters log
INFO:     Reduce shuffle bytes=0
aug 15, 2013 9:37:08 PM org.apache.hadoop.mapred.Counters log
INFO:     Reduce output records=11820
aug 15, 2013 9:37:08 PM org.apache.hadoop.mapred.Counters log
INFO:     Spilled Records=43234
aug 15, 2013 9:37:08 PM org.apache.hadoop.mapred.Counters log
INFO:     Map output bytes=481174
aug 15, 2013 9:37:08 PM org.apache.hadoop.mapred.Counters log
INFO:     Total committed heap usage (bytes)=362676224
aug 15, 2013 9:37:08 PM org.apache.hadoop.mapred.Counters log
INFO:     Combine input records=0
aug 15, 2013 9:37:08 PM org.apache.hadoop.mapred.Counters log
INFO:     Map output records=21617
aug 15, 2013 9:37:08 PM org.apache.hadoop.mapred.Counters log
INFO:     SPLIT_RAW_BYTES=108
aug 15, 2013 9:37:08 PM org.apache.hadoop.mapred.Counters log
INFO:     Reduce input records=21617Process finished with exit code 0

可以在提供的输出目录中找到此作业创建的输出文件,如以下屏幕截图所示:

屏幕截图-2013-08-15-at-21-42-49

如您所见,我们可以在IDE中(或从命令行)运行此main方法,但是我想在去之前在Mapper和Reducer上执行一些单元测试。 我将在另一篇文章中演示如何做到这一点。

参考:在The Pragmatic Integrator博客上,由我们的JCG合作伙伴 Pascal Alma 用 Java编写了Hadoop MapReduce任务 。

翻译自: https://www.javacodegeeks.com/2013/08/writing-a-hadoop-mapreduce-task-in-java.html

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/367631.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

java 大二学期总结报告_大二学生自我总结「」

大二学生导师工作总结转眼间&#xff0c;我们的大二学年就这样结束了&#xff0c;在迎接新的一学期前我们来写一份自我总结吧。下面是小编搜集整理的大二学生自我总结&#xff0c;欢迎阅读。更多资讯尽在自我总结栏目!大二学生自我总结回顾大学二年,通过良师的教导和自身的刻苦…

windows下揪出java程序占用cpu很高的线程

背景 天天搞java&#xff0c;这些监控也都知道&#xff0c;用过&#xff0c;但也没往细里追究。因为也没碰见这种问题&#xff0c;这次还是静下来走一遍流程吧。与网上基本一致&#xff0c;不过我区分了下linux和windows的不一样。我感觉基本是程序写成死循环了或者大对象分配多…

jquery -input事件

input输入框的change事件&#xff0c;要在input失去焦点的时候才会触发 $(input[namemyInput]).change(function() { ... }); 在输入框内容变化的时候不会触发change&#xff0c;当鼠标在其他地方点一下才会触发用下面的方法会生效&#xff0c;input [html] view plain copy$(&…

Bootstrap中的下拉列表

下拉列表&#xff08;select&#xff09;注意&#xff0c;很多原生选择菜单单 - 即在 Safari 和 Chrome 中 - 的圆角是无法通过修改 border-radius 属性来改变的。复制<select class"form-control"><option>1</option><option>2</option&…

Spring集成:轻量级集成方法

当今的应用程序希望能够访问企业环境中的所有业务&#xff0c;而无需考虑与绝望的系统无缝集成的应用程序技术。 可以通过使用中间件技术对各种系统进行布线来实现这种集成。 集成平台使应用程序可以相互共享信息的环境&#xff0c;从而使体系结构具有高度的互操作性。 Spring…

动态REM

什么是rem&#xff1f; rem是相对于根元素html字体大小来计算的&#xff0c;即( 1rem html字体大小 ) rem和em区别&#xff1f; rem:&#xff08;root em&#xff0c;根em&#xff09;根元素的fort-size的大小计算em&#xff1a;相对长度单位&#xff0c;相对于当前对象内文本…

java教学楼的属性_java设计一个父类建筑物building,由它派生出教学楼类classroom,然后采用一些数据进行测试....

public class Building {public String bname;//建筑物名称public int floors;//代表总层数public double area;//代表总面积public Building(){}public Building(String bname, int floors, double area) {this.bname bname;this.floors floors;this.area area;}}public cl…

Bootstrap中的列表的使用

列表无序列表排列顺序无关紧要的一列元素。Lorem ipsum dolor sit ametConsectetur adipiscing elitInteger molestie lorem at massaFacilisis in pretium nisl aliquetNulla volutpat aliquam velitPhasellus iaculis nequePurus sodales ultriciesVestibulum laoreet portti…

Vue项目中使用HighChart

记&#xff1a;初次在Vue项目中使用 HighChart 的时候要走的坑 感谢这位哥们的思路 传送门 Vue-cli项目使用 npm install highcharts --save 让我们看看 highcharts 的使用方法&#xff0c;传送门 Highcharts.chart(targetTag, option) 重启项目&#xff0c;建立chart.vue文件 …

form字体和颜色java安卓开发_Android 修改App中默认TextView的字体和颜色

一、别人怎么做来源http://stackoverflow.com/questions/3078081/setting-global-styles-for-views-in-androidActually, you can set a default style for TextViews (and most other built-in widgets) without needing to do a custom java class or setting the style indi…

使用Dozer框架进行Bean操作

介绍 如您所知&#xff0c;您可以在任何操作系统中将文件或文件夹从源位置复制到目标位置。 您是否考虑过复制基本上是POJO的java对象&#xff1f; 在许多情况下&#xff0c;您需要将源bean的内容复制到目标bean。 我不关心对象的拷贝构造函数&#xff0c;浅拷贝或深拷贝或克隆…

js如何把ajax获取的值返回到上层函数里?

我现在有个系统在用户点击浏览时&#xff0c;系统会以ajax的方式从后台获取查看的链接&#xff0c;并以window.open的方式打开&#xff0c;但因为现在多数的浏览器都会拦截window.open打开的地址&#xff0c;而window.location.href的方式又无法在浏览器新窗口打开&#xff0c;…

接口IDisposable的用法

C#的每一个类型都代表一种资源&#xff0c;而资源又分为两类&#xff1a; 托管资源 由CLR管理分配和释放的资源&#xff0c;即从CLR里new出来的对象。非托管资源 不受CLR管理的对象&#xff0c;如Windows内核对象&#xff0c;或者文件、数据库连接、套接字、COM对象等。如果类…

图形处理:betweeness中心性– neo4j的密码与graphstream

上周&#xff0c; 我写了关于中间性中心性算法以及使用graphstream 理解它的尝试 &#xff0c;在阅读源代码时&#xff0c;我意识到我可以使用neo4j的所有最短路径算法将某些东西放在一起。 概括地说&#xff0c;中间性中心度算法用于确定图中节点的负载和重要性。 在与Jen讨…

java tongpaiyu danliantiao_java版的汉字转拼音程序

[文件] ChiToLetter.javaimport java.io.UnsupportedEncodingException;import java.util.HashSet;import java.util.Iterator;import java.util.Set;import java.util.Vector;//实现汉字向拼音的转化//-----------------------------------------------------设计人:牛文平// …

小程序之Tab切换

小程序越来越火了&#xff0c;作为一名&#xff0c;额 有理想的攻城狮&#xff0c;当然要紧跟互联网时代的步伐啦&#xff0c;于是我赶紧抽时间学习了一下小程序的开发&#xff0c;顺便把经验分享给大家。 对于申请账号以及安装开发工具等&#xff0c;大家可以看官网&#xff…

configparser logging

configparser模块 # 该模块适用于配置文件的格式与windows ini文件类似&#xff0c;可以包含一个或多个节&#xff08;section&#xff09;&#xff0c;每个节可以有多个参数&#xff08;键值&#xff09;。 import configparser config configparser.ConfigParser() c…

JS结合Cookie实现验证码功能

验证码功能是现在网站开发中非常常见的一种功能&#xff0c;常见的编程语言&#xff0c;比如.NET,JAVA都能很容易实现验证码功能&#xff0c;今天我准备分享一个使用JS实现验证码的功能&#xff0c;非常简单使用&#xff0c;拿来就可以用&#xff0c;废话不多说&#xff0c;直接…

创建基于密码的加密密钥

本文讨论了创建基于密码的加密PBE密钥。 首先提醒您以前的要点–通常&#xff0c;在实际操作中&#xff0c;应将PBE密钥用作主密钥&#xff0c;该主密钥仅用于解锁工作密钥。 这具有三个主要优点&#xff1a; 您可以有多个密码&#xff0c;例如&#xff0c;托管的恢复密钥&am…

php-5.6.26源代码 - PHP文件汇编成opcode、执行

文件 php-5.6.26/Zend/zend.c ZEND_API int zend_execute_scripts(int type TSRMLS_DC, zval **retval, int file_count, ...) /* {{{ */ {va_list files;int i;zend_file_handle *file_handle;zend_op_array *orig_op_array EG(active_op_array); // 保存现场&#xff0c;操作…