MapReduce:通过数据密集型文本处理

自上次发布以来已经有一段时间了,因为我一直在忙于Coursera提供的一些课程。 有一些非常有趣的产品,值得一看。 前一段时间,我购买了Jimmy Lin和Chris Dyer的MapReduce数据密集型处理程序 。 本书以伪代码格式介绍了几种关键的MapReduce算法。 我的目标是采用第3-6章中介绍的算法,并以Hadoop: Tom White的《权威指南》为参考在Hadoop中实现它们。 我将假设您熟悉Hadoop和MapReduce,并且不介绍任何入门资料。 因此,让我们从局部聚合开始进入第3章-MapReduce算法设计。

本地聚集

在很高的级别上,当Mappers发出数据时,中间结果将写入磁盘,然后通过网络发送到Reducers以进行最终处理。 在处理MapReduce作业中,写入磁盘然后通过网络传输数据的延迟是一项昂贵的操作。 因此,有理由认为,只要有可能,减少从映射器发送的数据量将提高MapReduce作业的速度。 本地聚合是一种用于减少数据量并提高MapReduce工作效率的技术。 本地聚合不能代替reducers,因为我们需要一种方法来使用来自不同映射器的相同键来收集结果。 我们将考虑实现本地聚合的3种方法:

  1. 使用Hadoop Combiner函数。
  2. 文本处理和MapReduce书中介绍了两种“映射器”组合方法。

当然,任何优化都需要权衡取舍,我们也会对此进行讨论。
为了演示本地聚合,我们将使用hadoop-0.20.2-cdh3u3在MacBookPro上安装的伪分布式群集上,在Charles Dickens的纯文本版本的A Christmas Carol (从Project Gutenberg下载)上运行无处不在的字数统计作业。从Cloudera发行。 我计划在以后的文章中在具有更实际大小的数据的EC2集群上运行相同的实验。
合路器

组合器函数是扩展Reducer类的对象。 实际上,对于此处的示例,我们将重复使用单词计数作业中使用的相同的reduce。 设置MapReduce作业时会指定组合器功能,如下所示:

job.setReducerClass(TokenCountReducer.class);

这是化简器代码:

public class TokenCountReducer extends Reducer<Text,IntWritable,Text,IntWritable>{@Overrideprotected void reduce(Text key, Iterable<IntWritable> values, Context context) throws IOException, InterruptedException {int count = 0;for (IntWritable value : values) {count+= value.get();}context.write(key,new IntWritable(count));}
}

组合器的工作就是按照名称中的含义进行操作,聚合数据的最终结果是网络上的数据减少,从而使效率得到提高。 如前所述,请记住,仍然需要简化器将结果与来自不同映射器的相同键组合在一起。 由于组合器功能是一种优化,因此Hadoop框架无法保证组合器将被调用多少次(如果有的话)。

在Mapper组合选项1中

使用Combiners的第一种选择(图3.2,第41页)非常简单,对我们原始的字数映射器进行了一些修改:

public class PerDocumentMapper extends Mapper<LongWritable, Text, Text, IntWritable> {@Overrideprotected void map(LongWritable key, Text value, Context context) throws IOException, InterruptedException {IntWritable writableCount = new IntWritable();Text text = new Text();Map<String,Integer> tokenMap = new HashMap<String, Integer>();StringTokenizer tokenizer = new StringTokenizer(value.toString());while(tokenizer.hasMoreElements()){String token = tokenizer.nextToken();Integer count = tokenMap.get(token);if(count == null) count = new Integer(0);count+=1;tokenMap.put(token,count);}Set<String> keys = tokenMap.keySet();for (String s : keys) {text.set(s);writableCount.set(tokenMap.get(s));context.write(text,writableCount);}}
}

正如我们在这里看到的,对于遇到的每个单词,我们不会发出计数为1的单词,而是使用映射来跟踪已处理的每个单词。 然后,在处理完所有标记后,我们遍历该映射并发出该行中遇到的每个单词的总数。

在Mapper组合选项2中

映射器合并的第二个选项(图3.3,第41页)与上述示例非常相似,但有两个区别-创建哈希映射时和发出映射中包含的结果时。 在上面的示例中,创建了一个映射,并在每次调用map方法时将其内容通过电线转储。 在此示例中,我们将使地图成为实例变量,并将地图的实例化移动到我们的映射器中的setUp方法。 同样,在完成对mapper的所有调用并调用cleanUp方法之前,不会将映射的内容发送到reducers。

public class AllDocumentMapper extends Mapper<LongWritable,Text,Text,IntWritable> {private  Map<String,Integer> tokenMap;@Overrideprotected void setup(Context context) throws IOException, InterruptedException {tokenMap = new HashMap<String, Integer>();}@Overrideprotected void map(LongWritable key, Text value, Context context) throws IOException, InterruptedException {StringTokenizer tokenizer = new StringTokenizer(value.toString());while(tokenizer.hasMoreElements()){String token = tokenizer.nextToken();Integer count = tokenMap.get(token);if(count == null) count = new Integer(0);count+=1;tokenMap.put(token,count);}}@Overrideprotected void cleanup(Context context) throws IOException, InterruptedException {IntWritable writableCount = new IntWritable();Text text = new Text();Set<String> keys = tokenMap.keySet();for (String s : keys) {text.set(s);writableCount.set(tokenMap.get(s));context.write(text,writableCount);}}
}

从上面的代码示例中可以看到,在对map方法的所有调用中,映射器都跟踪唯一字数。 通过跟踪唯一令牌及其计数,应该大大减少发送给reducer的记录数量,这反过来又可以改善MapReduce作业的运行时间。 这样可以达到与使用MapReduce框架提供的Combiner Function选项相同的效果,但是在这种情况下,可以确保将调用组合代码。 但是这种方法也有一些警告。 在地图调用之间保持状态可能会出现问题,并且绝对违反“地图”功能的功能精神。 同样,通过保持所有映射器的状态,取决于作业中使用的数据,内存可能是另一个要解决的问题。 最终,必须权衡所有权衡以确定最佳方法。

结果

现在,让我们看一下不同映射器的一些结果。 由于作业是在伪分布式模式下运行的,因此实际的运行时间是无关紧要的,但是我们仍然可以推断出使用本地聚合会如何影响在实际集群上运行的MapReduce作业的效率。

每个令牌映射器:

12/09/13 21:25:32 INFO mapred.JobClient:     Reduce shuffle bytes=366010
12/09/13 21:25:32 INFO mapred.JobClient:     Reduce output records=7657
12/09/13 21:25:32 INFO mapred.JobClient:     Spilled Records=63118
12/09/13 21:25:32 INFO mapred.JobClient:     Map output bytes=302886

在Mapper精简选项1中:

12/09/13 21:28:15 INFO mapred.JobClient:     Reduce shuffle bytes=354112
12/09/13 21:28:15 INFO mapred.JobClient:     Reduce output records=7657
12/09/13 21:28:15 INFO mapred.JobClient:     Spilled Records=60704
12/09/13 21:28:15 INFO mapred.JobClient:     Map output bytes=293402

在Mapper精简选项2中:

12/09/13 21:30:49 INFO mapred.JobClient:     Reduce shuffle bytes=105885
12/09/13 21:30:49 INFO mapred.JobClient:     Reduce output records=7657
12/09/13 21:30:49 INFO mapred.JobClient:     Spilled Records=15314
12/09/13 21:30:49 INFO mapred.JobClient:     Map output bytes=90565

组合器选项:

12/09/13 21:22:18 INFO mapred.JobClient:     Reduce shuffle bytes=105885
12/09/13 21:22:18 INFO mapred.JobClient:     Reduce output records=7657
12/09/13 21:22:18 INFO mapred.JobClient:     Spilled Records=15314
12/09/13 21:22:18 INFO mapred.JobClient:     Map output bytes=302886
12/09/13 21:22:18 INFO mapred.JobClient:     Combine input records=31559
12/09/13 21:22:18 INFO mapred.JobClient:     Combine output records=7657

不出所料,没有合并的Mapper的结果最差,紧随其后的是第一个映射器内的合并选项(尽管如果在运行字数统计之前将数据清理干净,这些结果本来可以更好)。 第二个映射器内合并选项和合并器功能实际上具有相同的结果。 重要的事实是,作为前两个选项,两者产生的结果都减少了2/3,减少了混洗字节。 将通过网络发送到缩减程序的字节数量减少该数量一定会对MapReduce作业的效率产生积极影响。 这里要牢记一点,那就是合并器/映射器合并不能仅在所有MapReduce作业中使用,在这种情况下,字数计数非常适合于这种增强,但这可能并不总是正确的。

结论

正如您所看到的,在寻求提高MapReduce作业的性能时,需要认真考虑使用映射器内合并或Hadoop合并器功能的好处。 至于哪种方法,则要权衡每种方法的权衡。

相关链接

  • Jimmy Lin和Chris Dyer 使用MapReduce进行的数据密集型处理
  • Hadoop: Tom White 的权威指南
  • 来自博客的源代码
  • MRUnit用于单元测试Apache Hadoop映射减少工作
  • Gutenberg项目提供了大量纯文本格式的书籍,非常适合在本地测试Hadoop作业。

祝您编程愉快,别忘了分享!

参考: 《 随机编码》博客上的JCG合作伙伴 Bill Bejeck 提供的MapReduce数据密集型文本处理功能 。


翻译自: https://www.javacodegeeks.com/2012/09/mapreduce-working-through-data.html

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

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

相关文章

ubuntu(deepin)安装apache2并支持php7.0

linux虚拟机下用于开发环境测试&#xff0c;安装的apache和php7.0&#xff0c;但是简单安装完两者后apache并不能解析php&#xff0c;原因是确实apache的php扩展。 # 首先安装apache sudo apt-get install apache2 # 然后安装php7.0 sudo apt-get install php7.0 # 一般执行完这…

java applet 换行_Java复习题

一、选择题1.有Java语句如下&#xff0c;则说法正确的是()A.此语句是错误的B. a.length的值为5C. b.length的值为5D. a.length和b.length的值都为52.整数除法中&#xff0c;如果除数为0&#xff0c;则将导致的异常是( B )A. NullPointerExceptionB. ArithmeticExceptionC. Arra…

解决:MVC对象转json包含\r \n

项目中对象转json字符串时&#xff0c;如下&#xff1a;JsonSerializerSettings jsetting new JsonSerializerSettings(); jsetting.DefaultValueHandling DefaultValueHandling.Ignore; return JsonConvert.SerializeObject(resultMoldels, Formatting.Indented, jsetting);…

CSS 小结笔记之滑动门技术

所谓的滑动门技术&#xff0c;就是指盒子背景能够自动拉伸以适应不同长度的文本。即当文字增多时&#xff0c;背景看起来也会变长。 大多数应用于导航栏之中&#xff0c;如微信导航栏: 具体实现方法如下&#xff1a; 1、首先每一块文本内容是由a标签与span标签组成 <a hr…

使用API​​身份验证的Spring Security

背景 尽管有许多博客文章详细介绍了如何使用Spring Security&#xff0c;但是当问题域位于标准LDAP或数据库身份验证之外时&#xff0c;我仍然经常发现配置挑战。 在本文中&#xff0c;我将介绍一些针对Spring Security的简单自定义&#xff0c;使其能够与基于REST的API调用一起…

java nlpir_4-NLPIR汉语分词系统-JAVA

好吧&#xff0c;之前用的是旧版的&#xff0c;现在出了个新版的&#xff0c;优先选择用新版的哈。从官网下载相应的开发包&#xff0c;然后主要需要找到这几个东西添加到项目工程里面&#xff0c;1.Data文件夹 2.NLPIR_JNI.DLL 3.NLPIR.jar 4.nlpir.properties添加完那些东西后…

浅析C语言中assert的用法(转)

原文地址&#xff1a;http://www.jb51.net/article/39685.htm 以下是对C语言中assert的使用方法进行了介绍&#xff0c;需要的朋友可以参考下。 assert宏的原型定义在<assert.h>中&#xff0c;其作用是如果它的条件返回错误&#xff0c;则终止程序执行&#xff0c;原型定…

hihocoder offer收割编程练习赛12 D 寻找最大值

思路&#xff1a; 可能数据太水了&#xff0c;随便乱搞就过了。 实现&#xff1a; 1 #include <iostream>2 #include <cstdio>3 #include <algorithm>4 using namespace std;5 typedef long long ll;6 7 int a[100005], n;8 9 int main() 10 { 11 int t;…

vue error:The template root requires exactly one element.

error:[vue/valid-template-root] The template root requires exactly one element. 原因&#xff1a; 因为vue的模版中只有能一个根节点&#xff0c;所以在<template>中插入第二个元素就会报错 解决方案&#xff1a; 将<template>中的元素先用一个<div>…

测试驱动陷阱,第2部分

单元测试中单元的故事 在本文的上半部分 &#xff0c;您可能会看到一些不好但很流行的测试示例。 但是我不是一个专业评论家&#xff08;也被称为“巨魔”或“仇恨者”&#xff09;&#xff0c;没有任何建设性的话就抱怨。 多年的TDD教给我的不仅仅是事情会变得多么糟糕。 有许…

java 代码 设置环境变量_Java 配置环境变量教程

【声明】欢迎转载&#xff0c;但请保留文章原始出处→_→【正文】1、安装JDK开发环境开始安装JDK&#xff1a;修改安装目录如下&#xff1a;确定之后&#xff0c;单击“下一步”。注&#xff1a;当提示安装JRE时&#xff0c;可以选择不要安装。2、配置环境变量&#xff1a;对于…

组合数据类型练习,英文词频统计实例上(2017.9.22)

字典实例&#xff1a;建立学生学号成绩字典&#xff0c;做增删改查遍历操作。 sno[33号,34号,35号,36号] grade[100,90,80,120] d{33号:100,34号:90,35号:80,36号:120} print(d) print(每个学号对应分数:,d.items()) print(弹出35号的分数:,d.pop(35号)) print(获取学号:,d.key…

java 代码中设置 临时 环境变量

System.setProperty("hadoop.home.dir", "D:\\software\\software_install\\dev_install\\hadoop-2.4.1"); 转载于:https://www.cnblogs.com/zychengzhiit1/p/6662376.html

什么是快速开发框架

什么是快速开发框架 前言 做为一个程序员&#xff0c;在开发的过程中会发现&#xff0c;有框架同无框架&#xff0c;做起事来是完全不同的概念&#xff0c;关系到开发的效率、程序的健壮、性能、团队协作、后续功能维护、扩展......等方方面面的事情。很多朋友在学习搭建自己…

java中的math.abs_Java.math.BigDecimal.abs()方法

全屏Java.math.BigDecimal.abs()方法java.math.BigDecimal.abs()返回一个BigDecimal&#xff0c;其值是此BigDecimal的绝对值&#xff0c;其标度是this.scale()。声明以下是java.math.BigDecimal.abs()方法的声明public BigDecimal abs()参数NA返回值此方法返回的名为value&…

我需要多少内存

什么是保留堆&#xff1f; 我需要多少内存&#xff1f; 在构建解决方案&#xff0c;创建数据结构或选择算法时&#xff0c;您可能会问自己&#xff08;或其他人&#xff09;这个问题。 如果此图包含1,000,000条边并且我使用HashMap进行存储&#xff0c;此图是否适合我的3G堆&am…

C语言程序设计预报作业

1阅读邹欣老师的博客--师生关系,针对文中的几种师生关系谈谈你的看法&#xff0c;你期望的师生关系是什么样的&#xff1f; 答&#xff1a;我认为文中的师生关系都存在一些缺陷&#xff0c;第一种师生关系是建立在病态关系上的&#xff0c;学生不是植物自然有自己的思想。所以我…

浅谈23种设计模式

浅谈23种设计模式 类之间的关联关系&#xff1a;在使用Java、C#和C等编程语言实现关联关系时&#xff0c;通常将一个类作为另一个类的属性。   (1)双向关联&#xff0c;两个类互相为各自的属性&#xff0c;比如顾客类Customer和商品类Product&#xff0c;顾客拥有商品&#x…

网页布局基础

1、盒子模型的第一层到第五层&#xff1a; border、padding content、background-image、background-color、margin 2、清除浮动。对受到浮动影响的标签作以下操作&#xff1a; 1、clear: both; 2、clear: right; clear: left; 3、设置宽度width: 100%(或者固定宽度) overflow…

mysql与串口通信_虚拟机串口与主机串口通信·小程序(下)

上次说到的&#xff0c;不能做到实时通信。那么开两个进程就可以了&#xff0c;一个用来监听是否有消息传来&#xff0c;一个用来等待用户输入。那么&#xff0c;先来复习一下进程的相关概念。进程结构linux中进程包含PCB(进程控制块)、程序以及程序所操纵的数据结构集&#xf…