上一章我们编写了简单的 MapReduce 程序,掌握这些就能编写大多数数据处理的代码。但是 MapReduce 框架提供给用户的能力并不止如此,本章我们仍然以上一章 word count 为例,继续完善我们的数据处理代码。本章主要关注的重点包括三个部分:

  1. 完整的 map / reduce 任务,完整的 map 任务除了 map 方法里的逻辑外,还包括任务运行前的准备工作以及任务结束后的清理工作,reduce 任务也一样

  2. Counter 的作用,有时候为了统计程序运行中任务的状态,比如:某个异常出现的次数,因此需要一个计数器进行统计并输出

  3. 给 MapReduce 任务传自定义配置,命令行可以实现传参数,但是参数比较多的情况下,命令行参数不好维护且不具备很好的可读性,最好能够使用 Hadoop 配置文件中的那种格式配置

在这里, 我们仍然用上一章 word count 中的 map 任务, 区别是我们可以通过自定义配置实现只统计某个单词出现的次数,同时增加了计数功能。下面看下如何在 map 任务中实现上面这三个内容。

package com.cnblogs.duma.mapreduce;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.hadoop.conf.Configuration;
import org.apache.hadoop.io.IntWritable;
import org.apache.hadoop.io.Text;
import org.apache.hadoop.mapreduce.Counter;
import org.apache.hadoop.mapreduce.Mapper; import java.io.IOException; /**
* WordCountMapper 继承 Mapper 类,需要指定4个泛型类型,分别是
* 输入 key 类型:本例中输入的 key 为每行文本的行号,例子中用不到所以这里是 Object
* 输入 value 类型:本例中输入的 value 是每行文本,因此是Text
* 输出 key 类型:map 输出的是每个单词,类型为 Text
* 输出 value 类型:单词出现的次数,为 1,因此类型 IntWritable
*/
public class WordCountMapper
extends Mapper<Object, Text, Text, IntWritable> {
/**
* 把每个单词映射成 <word, 1> 的格式
*/
private final static IntWritable one = new IntWritable();
private Text outWord = new Text();
private String filterWord; /**
* 每一个 map 进程调用一次
* @param context
* @throws IOException
* @throws InterruptedException
*/
@Override
protected void setup(Context context) throws IOException, InterruptedException {
Configuration conf = context.getConfiguration();
filterWord = conf.get("wordcount.filter.word", null); /**
* 初始化工作, 比如连接数据库
*/
} /**
* 每个 map 方法处理一行数据
* @param key 输入的行号
* @param value 每一行文本
* @param context
* @throws IOException
* @throws InterruptedException
*/
@Override
protected void map(Object key, Text value, Context context) throws IOException, InterruptedException {
String[] words = value.toString().split(" "); //空格分割一行中的每个单词
Counter counter = context.getCounter("group1", "counter1"); //第一个参数代表计数组,第二个参数代表计数名称 for (String word : words) {
if (filterWord != null && !filterWord.equals(word)) //判断是否只统计过滤词
continue; counter.increment(); // 计数
outWord.set(word);
context.write(outWord, one); // map输出
}
} @Override
protected void cleanup(Context context) throws IOException, InterruptedException {
/**
* 做清理工作, 比如释放数据库连接
*/
}
}

WordCounterMapper类的定义与上一章一样,只是针对上述三个问题做出了相应的修改:

  1. 增加 setup 和 cleanup 方法,假设 map 任务中需要获取数据库里的内容,由于连接数据库的操作需要消耗资源,且每个 map 任务连接一次数据库即可,因此连接数据库的操作可以写在 setup 方法中。setup 方法在 map 方法开始前调用一次。同理 cleanup 方法在 map 方法执行完后调用一次,释放数据库连接防止内存泄漏。

  2. 在 map 方法中增加了计数的功能,counter.increment(1);,该计数器为了统计 map 方法中具体处理了多少个单词。实际应用中我们可能想对抛异常的业务逻辑做计数,这样日后可以通过分析 MapReduce 输出的计数日志,来统计出错的次数。

  3. setup 方法中有个获取配置的代码,wordcount.filter.word 代表只对某个词做统计,这个配置是我们自定义的,看上去跟 Hadoop 系统配置写法类似,这种写法见名知意,方便维护。

为了上述代码顺利执行,我们需要修改下驱动程序

package com.cnblogs.duma.mapreduce;

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 java.io.IOException; public class WordCount {
public static void main(String[] args) throws IOException, ClassNotFoundException, InterruptedException {
Configuration conf = new Configuration();
GenericOptionsParser optionParser = new GenericOptionsParser(conf, args); //识别命令行参数中的自定义配置
String[] remainingArgs = optionParser.getRemainingArgs(); //获取处理自定义配置外的其他参数
... FileInputFormat.addInputPath(job, new Path(remainingArgs[0])); //增加输入文件
FileOutputFormat.setOutputPath(job, new Path(remainingArgs[1])); //设置输出目录 System.exit(job.waitForCompletion(true) ? 0 : 1);
}

代码跟上一章基本一致, 增加了能够处理自定义配置的代码。打包,上传到 hadoop0 机器, 执行以下命令启动程序

hadoop jar hadoop-ex-1.0-SNAPSHOT.jar com.cnblogs.duma.mapreduce.WordCount -Dwordcount.filter.word=hadoop /hadoop-ex/wordcount/input /hadoop-ex/wordcount/output

首先,我们看到任务的启动命令比上一章多了 -Dwordcount.filter.word=hadoop,-D 后面跟的就是配置的 key,= 后面跟的是配置的 value。这个配置让我们的程序只统计 hadoop 这个词出现的次数。如果驱动程序中不加 new GenericOptionsParser(conf, args) 这段代码,那么 -Dwordcount.filter.word=hadoop 就被看做是普通命令行参数, args[0] = "-Dwordcount.filter.word=hadoop" 。有兴趣的读者可以自己试试,同时也可以看下 GenericOptionsParser 的代码。任务执行完可以看到以下的输出信息

Map-Reduce Framework
Map input records=4
Map output records=3
Map output bytes=33
Map output materialized bytes=51
Input split bytes=233
Combine input records=0
Combine output records=0
Reduce input groups=1
Reduce shuffle bytes=51
Reduce input records=3
Reduce output records=1
Spilled Records=6
Shuffled Maps =2
Failed Shuffles=0
Merged Map outputs=2
GC time elapsed (ms)=981
CPU time spent (ms)=2390
Physical memory (bytes) snapshot=540434432
Virtual memory (bytes) snapshot=6240616448
Total committed heap usage (bytes)=262197248
Shuffle Errors
BAD_ID=0
CONNECTION=0
IO_ERROR=0
WRONG_LENGTH=0
WRONG_MAP=0
WRONG_REDUCE=0
group1
counter1=3

可以看到 MapReduce 有系统默认的计数器, 比如:Map input records=4 代表一共输入了 4 条记录。我们能看到自定义的计数器 counter1=3 ,之前解释过这个代表一共处理了多少个词, 这里是 3 也是对的, 因为 hadoop 这个词出现了 3 次。再看下输出结果

[root@hadoop0 hadoop-ex]# hadoop fs -cat /hadoop-ex/wordcount/output/*
hadoop 3

输出是符合预期的,只统计了 hadoop 这个词且出现了 3 次。

以上便是这章的主要内容,这里虽然以 map 任务举例,但这三点同样可以在 reduce 任务中应用。掌握这些内容编写大多数 MapReduce 任务基本没有问题。

番外

这篇文章我们知道一个 map 或 reduce 任务只会执行一次 setup 和 cleanup 方法,我们实际看下 Hadoop 源码中是如何实现的。以 WordCountMapper 为例, 它继承了 Mapper 类, 在 Mapper 类中有一个 run 方法

/**
* Expert users can override this method for more complete control over the
* execution of the Mapper.
* @param context
* @throws IOException
*/
public void run(Context context) throws IOException, InterruptedException {
setup(context);
try {
while (context.nextKeyValue()) {
map(context.getCurrentKey(), context.getCurrentValue(), context);
}
} finally {
cleanup(context);
}
}

可以看到, 函数第一行调用一次 setup 方法,循环获取每个 key - value 对,即 <行号, 每行文本> 调用 map 方法进行处理。处理完毕后调用 cleanup 方法结束任务。

以上便是本章的内容,如有疑问、错误、期待的内容,欢迎留言交流。

大数据技术 - 通俗理解MapReduce之WordCount(三)的更多相关文章

  1. 大数据技术 - 通俗理解MapReduce之WordCount(二)

    上一章我们搭建了分布式的 Hadoop 集群.本章我们介绍 Hadoop 框架中的一个核心模块 - MapReduce.MapReduce 是并行计算模块,顾名思义,它包含两个主要的阶段,map 阶段 ...

  2. 大数据技术 - MapReduce的Combiner介绍

    本章来简单介绍下 Hadoop MapReduce 中的 Combiner.Combiner 是为了聚合数据而出现的,那为什么要聚合数据呢?因为我们知道 Shuffle 过程是消耗网络IO 和 磁盘I ...

  3. 【学习笔记】大数据技术原理与应用(MOOC视频、厦门大学林子雨)

    1 大数据概述 大数据特性:4v volume velocity variety value 即大量化.快速化.多样化.价值密度低 数据量大:大数据摩尔定律 快速化:从数据的生成到消耗,时间窗口小,可 ...

  4. 大数据技术 - 为什么是SQL

    在大数据处理以及分析中 SQL 的普及率非常高,几乎是每一个大数据工程师必须掌握的语言,甚至非数据处理岗位的人也在学习使用 SQL.今天这篇文章就聊聊 SQL 在数据分析中作用以及掌握 SQL 的必要 ...

  5. TOP100summit:【分享实录-WalmartLabs】利用开源大数据技术构建WMX广告效益分析平台

    本篇文章内容来自2016年TOP100summitWalmartLabs实验室广告平台首席工程师.架构师粟迪夫的案例分享. 编辑:Cynthia 粟迪夫:WalmartLabs实验室广告平台首席工程师 ...

  6. Google大数据技术架构探秘

    原文地址:https://blog.csdn.net/bingdata123/article/details/79927507 Google是大数据时代的奠基者,其大数据技术架构一直是互联网公司争相学 ...

  7. 大数据技术之Hadoop入门

      第1章 大数据概论 1.1 大数据概念 大数据概念如图2-1 所示. 图2-1 大数据概念 1.2 大数据特点(4V) 大数据特点如图2-2,2-3,2-4,2-5所示 图2-2 大数据特点之大量 ...

  8. 除Hadoop大数据技术外,还需了解的九大技术

    除Hadoop外的9个大数据技术: 1.Apache Flink 2.Apache Samza 3.Google Cloud Data Flow 4.StreamSets 5.Tensor Flow ...

  9. 参加2013中国大数据技术大会(BDTC2013)

    2013年12月5日-6日参加了为期两天的2013中国大数据技术大会(Big Data Technology Conference, BDTC2013),本期会议主题是:“应用驱动的架构与技术 ”.大 ...

随机推荐

  1. Confluence 6 手动备份站点

    Confluence 被配置自动备份数据,使用压缩的 XML 格式.同时你也可以通过 Confluence 的 管理员控制台(Administration Console)手动进行备份. 你需要具有 ...

  2. matlab 测试 数字二次混频

    % test2 clear; clf; close all Fs=800000;%采样频率800k fz=80000;%载波频率80k fz1=3000;%载波频率3k fj=79000;%基波频率7 ...

  3. 1706: 神奇的编码(zzuli)

    题目描述 假如没有阿拉伯数字,我们要怎么表示数字呢 小明想了一个方法如下: 1 -> A 2 -> B 3 -> C .... 25 -> Y 26 -> Z 27 -& ...

  4. ES6 Promise 全面总结

    转载:点击查看原文 ES6 Promise对象 ES6中,新增了Promise对象,它主要用于处理异步回调代码,让代码不至于陷入回调嵌套的死路中. @-v-@ 1. Promise本质 Promise ...

  5. logical_backup: expdp/impdp

    Table of Contents 1. 注意事项 2. 前期准备 3. 常用参数及示例 4. 常用语句示例 5. 交互式命令 6. 技巧 6.1. 不生成文件直接导入目标数据库 6.2. 通过she ...

  6. Command 'ifconfig' not found, but can be installed with: sudo apt install net-tools

    然后按照错误信息安安装网络工具: sudo apt install net-tools shl@shl-tx:~$ sudo apt install net-tools正在读取软件包列表... 完成正 ...

  7. 51 Nod 1242 斐波那契数列的第N项(矩阵快速幂模板题)

    1242 斐波那契数列的第N项  基准时间限制:1 秒 空间限制:131072 KB 分值: 0 难度:基础题  收藏  关注 斐波那契数列的定义如下: F(0) = 0 F(1) = 1 F(n) ...

  8. Spring Boot学习--项目启动时执行指定service的指定方法

    Springboot给我们提供了两种“开机启动”某些方法的方式:ApplicationRunner和CommandLineRunner. 这两种方法提供的目的是为了满足,在项目启动的时候立刻执行某些方 ...

  9. 史上最简单的 SpringCloud 教程

    史上最简单的 SpringCloud 教程 | 第一篇: 服务的注册与发现(Eureka)史上最简单的SpringCloud教程 | 第二篇: 服务消费者(rest+ribbon)史上最简单的Spri ...

  10. Django_Admin操作

    Django_Admin 创建Django_Admin 管理账户 D:\github\Django_Aadmin>python manage.py createsuperuser Usernam ...