本篇介绍MapReduce的一些高级特性,如计数器、数据集的排序和连接。计数器是一种收集作业统计信息的有效手段。排序是MapReduce的核心技术,MapReduce也可以运行大型数据集间的“”连接(join)操作。

计数器

计数器是一种收集作业统计信息的有效手段,用于质量控制或应用级统计。计数器还可用于辅助诊断系统故障。对于大型分布式系统来说,获取计数器比分析日志文件easy的多。

演示样例一:气温缺失及不规则数据计数器

import java.io.IOException;
import java.util.Iterator; import org.apache.hadoop.conf.Configured;
import org.apache.hadoop.io.*;
import org.apache.hadoop.mapred.JobClient;
import org.apache.hadoop.mapred.JobConf;
import org.apache.hadoop.mapred.MapReduceBase;
import org.apache.hadoop.mapred.Mapper;
import org.apache.hadoop.mapred.OutputCollector;
import org.apache.hadoop.mapred.Reducer;
import org.apache.hadoop.mapred.Reporter;
import org.apache.hadoop.util.Tool;
import org.apache.hadoop.util.ToolRunner; //统计最高气温的作业。也统计气温值缺少的记录,不规范的记录
public class MaxTemperatureWithCounters extends Configured implements Tool { enum Temperature {
MiSSING, MALFORMED
} static class MaxTemeratureMapperWithCounters extends MapReduceBase implements
Mapper<LongWritable, Text, Text, IntWritable> { private NcdcRecordParser parser = new NcdcRecordParser(); @Override
public void map(LongWritable key, Text value,
OutputCollector<Text, IntWritable> output, Reporter reporter)
throws IOException {
parser.parse(value);
if (parser.isValidTemperature()) {
int airTemperature = parser.getAirTemperature();
output.collect(new Text(parser.getYear()), new IntWritable(
airTemperature));
} else if (parser.isMa1formedTemperature()) {
reporter.incrCounter(Temperature.MALFORMED, 1);
} else if (parser.IsMissingTemperature()) {
reporter.incrCounter(Temperature.MALFORMED, 1);
} } } static class MaxTemperatureReduceWithCounters extends MapReduceBase implements
Reducer<Text, IntWritable, Text, IntWritable> {
public void reduce(Text key, Iterator<IntWritable> values,
OutputCollector<Text, IntWritable> output, Reporter reporter)
throws IOException {
int maxValue = Integer.MIN_VALUE;
while (values.hasNext()) {
maxValue = Math.max(maxValue, values.next().get());
}
output.collect(key, new IntWritable(maxValue)); }
} @Override
public int run(String[] args) throws Exception {
args = new String[] { "/test/input/t", "/test/output/t" }; // 给定输入输出路径
JobConf conf = JobBuilder.parseInputAndOutput(this, getConf(), args);
if (conf == null) {
return -1;
}
conf.setOutputKeyClass(Text.class);
conf.setOutputValueClass(IntWritable.class);
conf.setMapperClass(MaxTemeratureMapperWithCounters.class);
conf.setCombinerClass(MaxTemperatureReduceWithCounters.class);
conf.setReducerClass(MaxTemperatureReduceWithCounters.class);
JobClient.runJob(conf);
return 0;
} public static void main(String[] args) throws Exception {
int exitCode = ToolRunner.run(new MaxTemperatureWithCounters(), args);
System.exit(exitCode);
}
}

演示样例二:统计气温信息缺失记录所占比例

import org.apache.hadoop.conf.*;
import org.apache.hadoop.mapred.*;
import org.apache.hadoop.util.*;
//统计气温缺失记录所占比例 public class MissingTemperatureFields extends Configured implements Tool { @Override
public int run(String[] args) throws Exception {
String jobID = args[0];
JobClient jobClient = new JobClient(new JobConf(getConf()));
RunningJob job = jobClient.getJob(JobID.forName(jobID));
if (job == null) {
System.err.printf("No job with ID %s found.\n", jobID);
return -1;
}
if (!job.isComplete()) {
System.err.printf("Job %s is not complete.\n", jobID);
return -1;
}
Counters counters = job.getCounters();
long missing = counters
.getCounter(MaxTemperatureWithCounters.Temperature.MiSSING);
long total = counters.findCounter(
"org.apache.hadoop.mapred.Task$Counter", "MAP_INPUT_RECORDS")
.getCounter();
System.out.printf("Records with missing temperature fields:%.2f%%\n",
100.0 * missing / total);
return 0;
} public static void main(String[] args) throws Exception {
int exitCode = ToolRunner.run(new MissingTemperatureFields(), args);
System.exit(exitCode);
}
}

hadoop jar xx.jar MissingTemperatureFields job_1400072670556_0001

排序

排序是MapReduce的核心技术。

虽然应用本身可能并不须要对数据排序,但仍可能使用MapReduce的排序功能来组织数据。以下将讨论几种不同的数据集排序方法。以及怎样控制MapReduce的排序。

实例一、数据准备:将天气数据转成顺序文件格式

import java.io.IOException;

import org.apache.hadoop.conf.*;
import org.apache.hadoop.io.*;
import org.apache.hadoop.io.SequenceFile.CompressionType;
import org.apache.hadoop.io.compress.GzipCodec;
import org.apache.hadoop.mapred.*;
import org.apache.hadoop.util.*; public class SortDataPreprocessor extends Configured implements Tool {
static class CleanerMapper extends MapReduceBase implements
Mapper<LongWritable, Text, IntWritable, Text> { private NcdcRecordParser parser = new NcdcRecordParser(); @Override
public void map(LongWritable key, Text value,
OutputCollector<IntWritable, Text> output, Reporter reporter)
throws IOException {
parser.parse(value);
if (parser.isValidTemperature()) {
output.collect(new IntWritable(parser.getAirTemperature()),
value);
}
}
} @Override
public int run(String[] args) throws Exception {
args = new String[] { "/test/input/t", "/test/input/seq" };
JobConf conf = JobBuilder.parseInputAndOutput(this, getConf(), args);
if (conf == null) {
return -1;
}
conf.setMapperClass(CleanerMapper.class);
conf.setOutputKeyClass(IntWritable.class);
conf.setOutputValueClass(Text.class);
conf.setNumReduceTasks(0);
conf.setOutputFormat(SequenceFileOutputFormat.class);
SequenceFileOutputFormat.setCompressOutput(conf, true);
SequenceFileOutputFormat
.setOutputCompressorClass(conf, GzipCodec.class);
SequenceFileOutputFormat.setOutputCompressionType(conf,
CompressionType.BLOCK);
JobClient.runJob(conf);
return 0;
} public static void main(String[] args) throws Exception {
int exitCode = ToolRunner.run(new SortDataPreprocessor(), args);
System.exit(exitCode);
}
}

演示样例二、部分排序

import org.apache.hadoop.conf.*;
import org.apache.hadoop.io.*;
import org.apache.hadoop.io.SequenceFile.CompressionType;
import org.apache.hadoop.io.compress.GzipCodec;
import org.apache.hadoop.mapred.*;
import org.apache.hadoop.util.*; public class SortByTemperatureUsingHashPartitioner extends Configured implements
Tool { @Override
public int run(String[] args) throws Exception {
args = new String[] { "/test/input/seq", "/test/output/t" };
JobConf conf = JobBuilder.parseInputAndOutput(this, getConf(), args);
if (conf == null) {
return -1;
}
conf.setInputFormat(SequenceFileInputFormat.class);
conf.setOutputKeyClass(IntWritable.class);
conf.setOutputFormat(SequenceFileOutputFormat.class);
conf.setNumReduceTasks(5);//设置5个reduce任务。输出5个文件
SequenceFileOutputFormat.setCompressOutput(conf, true);
SequenceFileOutputFormat
.setOutputCompressorClass(conf, GzipCodec.class);
SequenceFileOutputFormat.setOutputCompressionType(conf,
CompressionType.BLOCK);
JobClient.runJob(conf);
return 0;
} public static void main(String[] args) throws Exception {
int exitCode = ToolRunner.run(
new SortByTemperatureUsingHashPartitioner(), args);
System.exit(exitCode);
} }

hadoop jar test.jar SortByTemperatureUsingHashPartitioner -D mapred.reduce.tasks=30

产生多个已经排好序的小文件。

连接

MapReduce可以运行大型数据集间的“”连接(join)操作,可是从头编写相关代码来运行连接比較麻烦。

也可以考虑使用一个更高级的框架,如Pig、Hive或Casading等。它们都将连接操作视为整个实现的核心部分。

本章的代码用到的基础工具类

其它章节也可能用到:)

JobBuilder

import org.apache.hadoop.conf.Configuration;
import org.apache.hadoop.fs.Path;
import org.apache.hadoop.mapred.FileInputFormat;
import org.apache.hadoop.mapred.FileOutputFormat;
import org.apache.hadoop.mapred.JobConf;
import org.apache.hadoop.util.Tool; public class JobBuilder { public static JobConf parseInputAndOutput(Tool tool, Configuration conf,
String[] args) {
if (args.length != 2) {
printUsage(tool, "<input><output>");
return null;
}
JobConf jobConf = new JobConf(conf, tool.getClass());
FileInputFormat.addInputPath(jobConf, new Path(args[0]));
FileOutputFormat.setOutputPath(jobConf, new Path(args[1]));
return jobConf;
} public static void printUsage(Tool tool, String extraArgsUsage) {
System.err.printf("Usage:%s [genericOptions] %s\n\n", tool.getClass()
.getSimpleName(), extraArgsUsage);
}
}

NcdcRecordParser

import org.apache.hadoop.io.Text;

public class NcdcRecordParser {
private static final int MISSING_TEMPERATURE = 9999; private String year;
private int airTemperature;
private String quality; public void parse(String record) {
year = record.substring(15, 19);
String airTemperatureString;
// Remove leading plus sign as parseInt doesn't like them
if (record.charAt(87) == '+') {
airTemperatureString = record.substring(88, 92);
} else {
airTemperatureString = record.substring(87, 92);
}
airTemperature = Integer.parseInt(airTemperatureString);
quality = record.substring(92, 93);
} public void parse(Text record) {
parse(record.toString());
} public boolean isValidTemperature() {
return airTemperature != MISSING_TEMPERATURE
&& quality.matches("[01459]");
} public boolean isMa1formedTemperature() {
return !quality.matches("[01459]");
} public boolean IsMissingTemperature() {
return airTemperature == MISSING_TEMPERATURE;
} public String getYear() {
return year;
} public int getAirTemperature() {
return airTemperature;
}
}

这一篇是《Hadoop权威指南》第八章的学习笔记,好久没看Hadoop,工作中也没使用,前不久学习的东西。忘记了非常多。学以致用是非常重要的。没用应用的学习,终于会忘记大部分,感兴趣的就须要多多温习了。

MapReduce编程实战之“高级特性”的更多相关文章

  1. (升级版)Spark从入门到精通(Scala编程、案例实战、高级特性、Spark内核源码剖析、Hadoop高端)

    本课程主要讲解目前大数据领域最热门.最火爆.最有前景的技术——Spark.在本课程中,会从浅入深,基于大量案例实战,深度剖析和讲解Spark,并且会包含完全从企业真实复杂业务需求中抽取出的案例实战.课 ...

  2. php面向对象编程学习之高级特性

    前几天写了一篇关于php面向对象基础知识的博客,这两天看了php面向对象的高级特性,写出来记录一下吧,方便以后拿出来复习. 面向对象除了最基本的定义类之外,最主要就是因为面向的一些高级特性,运用这些高 ...

  3. MapReduce编程实战之“调试”和&quot;调优&quot;

    本篇内容 在上一篇的"初识"环节,我们已经在本地和Hadoop集群中,成功的执行了几个MapReduce程序,对MapReduce编程,已经有了最初的理解. 在本篇文章中,我们对M ...

  4. RabbitMQ实战(三)-高级特性

    0 相关源码 1 你将学到 如何保证消息百分百投递成功 幂等性 如何避免海量订单生成时消息的重复消费 Confirm确认消息.Return返回消息 自定义消费者 消息的ACK与重回队列 限流 TTL ...

  5. MapReduce(二) MR的高级特性-序列化、排序、分区、合并

    一.序列化   (*) 核心接口:Writable接口.如果有一个类实现了Writable接口,就可以作为Map/Reduce的key和value.    举例: 读取员工数据,生成员工对象,直接存储 ...

  6. 云端卫士实战录 | Java高级特性之多线程

    <实战录>导语 一转眼作为一名Java开发者已经四年多时间了,说长不长说短不短,对于java的感情还是比较深的,主要嘛毕竟它给了我饭吃.哈哈,开个玩笑.今天我想借此机会来和大家聊聊Java ...

  7. Shell高级编程视频教程-跟着老男孩一步步学习Shell高级编程实战视频教程

    Shell高级编程视频教程-跟着老男孩一步步学习Shell高级编程实战视频教程 教程简介: 本教程共71节,主要介绍了shell的相关知识教程,如shell编程需要的基础知识储备.shell脚本概念介 ...

  8. 跟着老男孩一步步学习Shell高级编程实战

    原创作品,允许转载,转载时请务必以超链接形式标明文章 原始出处 .作者信息和本声明.否则将追究法律责任.http://oldboy.blog.51cto.com/2561410/1264627 本sh ...

  9. activemq的高级特性:集群实战

    高级特性实战需求 当消费端是多个集群,集群A又包含多个服务. 当每个集群都要接受相同的一批消息,而集群内的每个服务都去分摊消息. 解决办法一:级联 增加一个中转者.但是不是特别的优化,而且性能也不是特 ...

随机推荐

  1. ACM_三元一次函数解法(克莱姆法则)

    三元一次函数 Time Limit: 2000/1000ms (Java/Others) Problem Description: 计算三元一次函数..如图 Input: EOF,先输入n,表示样例个 ...

  2. 3CSS基本语法

    ------------------------- --------------------------------------- -------------------------------- & ...

  3. Jquery课堂上课了,第一节Jquery选择器$

    Jquery是优秀的Javascrīpt框架,$是jquery库的申明,它很不稳定(我就常遇上),换一种稳定的写法jQuery.noConflict();                   jQue ...

  4. Java系列学习(十四)-集合

    1.java中的集合学习 2.Collection中常用方法 1.添加功能 boolean add(E e):添加一个元素 boolean addAll(Collection<? extends ...

  5. Struts之 拦截器配置 ( Interceptor )

    struts2体系结构的核心就是拦截器. 以链式执行,对真正要执行的方法(execute())进行拦截.首先执行Action配置的拦截器,在Action和Result执行之后,拦截器再一次执行(与先前 ...

  6. Android 自己搭建一个直播系统吧

    服务端用 SRS(Simple Rtmp Server),在这里下载simple-rtmp-server需要Linux系统最好是Ubuntu,装个Ubuntu虚拟机就行了在Linux里,解压缩SRS ...

  7. PHP开发之旅-验证码功能实现

    验证码这样的功能可以说是无处不在了,接下来使用php来实现验证码这样的功能,这里我是将验证码实现抽取到一个类中独立开来,那么后面如果再使用到验证码功能,直接引入该类文件并创建该类的实例,就可以使用验证 ...

  8. 多线程-实现Runnable接口

    当一个任务或者函数多个线程同时调用时仅仅继承Thread是不行的.需要实现Runnable接口. 好处: 1.将线程的任务从线程的子类中分离出来,进行了单独的封装. 按照面向对象的思想将任务封装成对象 ...

  9. 【sqli-labs】 less53 GET -Blind based -Order By Clause -String -Stacked injection(GET型基于盲注的字符型Order By从句堆叠注入)

    http://192.168.136.128/sqli-labs-master/Less-53/?sort=1';insert into users(id,username,password) val ...

  10. Windows Phone 8: NavigationInTransition实现页面切换效果

    NavigationInTransition这个是实现页面切换效果,而且没控件来拖,要自己手动写, 将App.xaml.cs中InitializePhoneApplication()函数里的RootF ...