• Hadoop程序开发的独门绝技
  • 在本地,伪分布和全分布模式下调试程序
  • 程序输出的完整性检查和回归测试
  • 日志和监控
  • 性能调优
 
1、开发MapReduce程序
 
[本地模式]
 
     本地模式下的hadoop将所有的运行都放在一个单独的Java虚拟机中完成,并且使用的是本地文件系统(非HDFS)。在本地模式中运行的程序将所有的日志和错误信息都输出到控制台,最后它会给出所处理数据的总量。
 
对程序进行正确性检查:
  • 完整性检查
  • 回归测试
  • 考虑使用long而非int
 
 
[伪分布模式]
 
本地模式不具备生产型hadoop集群的分布式特征。一些bug在运行本地模式时是不会出现的。现在是通过日志文件和web界面远程监视它,这些工具和以后在监控生产集群时用的工具是相同的。
 
2、生产集群上的监视和调试
 
[计数器]
 

代码清单 使用计数器统计缺失值个数的MapClass
 
 import java.io.IOException;
import java.util.regex.PatternSyntaxException;
import java.util.Iterator; import org.apache.hadoop.conf.Configuration;
import org.apache.hadoop.conf.Configured;
import org.apache.hadoop.fs.Path;
import org.apache.hadoop.io.IntWritable;
import org.apache.hadoop.io.LongWritable;
import org.apache.hadoop.io.DoubleWritable;
import org.apache.hadoop.io.Text;
import org.apache.hadoop.mapred.*;
import org.apache.hadoop.util.Tool;
import org.apache.hadoop.util.ToolRunner; public class AveragingWithCombiner extends Configured implements Tool { public static class MapClass extends MapReduceBase
implements Mapper<LongWritable, Text, Text, Text> { static enum ClaimsCounters { MISSING, QUOTED }; public void map(LongWritable key, Text value,
OutputCollector<Text, Text> output,
Reporter reporter) throws IOException { String fields[] = value.toString().split(",", -20);
String country = fields[4];
String numClaims = fields[8];
if (numClaims.length() == 0) {
reporter.incrCounter(ClaimsCounters.MISSING, 1);
} else if (numClaims.startsWith("\"")) {
reporter.incrCounter(ClaimsCounters.QUOTED, 1);
} else {
output.collect(new Text(country), new Text(numClaims + ",1"));
} }
} public static class Combine extends MapReduceBase
implements Reducer<Text, Text, Text, Text> { public void reduce(Text key, Iterator<Text> values,
OutputCollector<Text, Text> output,
Reporter reporter) throws IOException { double sum = 0;
int count = 0;
while (values.hasNext()) {
String fields[] = values.next().toString().split(",");
sum += Double.parseDouble(fields[0]);
count += Integer.parseInt(fields[1]);
}
output.collect(key, new Text(sum + "," + count));
}
} public static class Reduce extends MapReduceBase
implements Reducer<Text, Text, Text, DoubleWritable> { public void reduce(Text key, Iterator<Text> values,
OutputCollector<Text, DoubleWritable> output,
Reporter reporter) throws IOException { double sum = 0;
int count = 0;
while (values.hasNext()) {
String fields[] = values.next().toString().split(",");
sum += Double.parseDouble(fields[0]);
count += Integer.parseInt(fields[1]);
}
output.collect(key, new DoubleWritable(sum/count));
}
} public int run(String[] args) throws Exception {
// Configuration processed by ToolRunner
Configuration conf = getConf(); // Create a JobConf using the processed conf
JobConf job = new JobConf(conf, AveragingWithCombiner.class); // Process custom command-line options
Path in = new Path(args[0]);
Path out = new Path(args[1]);
FileInputFormat.setInputPaths(job, in);
FileOutputFormat.setOutputPath(job, out); // Specify various job-specific parameters
job.setJobName("AveragingWithCombiner");
job.setMapperClass(MapClass.class);
job.setCombinerClass(Combine.class);
job.setReducerClass(Reduce.class); job.setInputFormat(TextInputFormat.class);
job.setOutputFormat(TextOutputFormat.class);
job.setOutputKeyClass(Text.class);
job.setOutputValueClass(Text.class); // Submit the job, then poll for progress until the job is complete
JobClient.runJob(job); return 0;
} public static void main(String[] args) throws Exception {
// Let ToolRunner handle generic command-line options
int res = ToolRunner.run(new Configuration(), new AveragingWithCombiner(), args); System.exit(res);
}
}
 

 
[跳过坏记录]
 
(1)在Java中配置记录跳读
 
     hadoop从0.19版本起就已经支持skipping特征了,但默认状态是关闭的。在Java中,这个特征由类SkipBadRecords来控制,全部由静态方法组成。作业的driver需要调用如下的一个或全部方法:
     public static void setMapperMaxSkipRecords(Configuration conf, long maxSkipRecs)
     public static void setReducerMaxSkipGroups(Configuration conf, long maxSkipRecs)
来分别为map任务和reduce任务打开记录跳读的设置。如果最大的跳读区域大小被设置为0(默认),那么记录跳读就处于关闭状态。可以使用JobConf.setMaxMapAttempts()和JobConf.setMaxReduceAttempts()方法,或者设置等效的属性mapred.map.max.attempts和mapred.reduce.max.attempts来做到这点。
 
     如果skipping被启用,hadoop在任务失效两次后就进入skipping模式。你可以在SkipBadRecords的setAttemptsToStartSkipping()方法中设置触发skipping模式的任务失效次数:
     public static void setAttemptsToStartSkipping(Configuration conf, int attemptsToStartSkipping)
hadoop会把被跳过的记录写入HDFS以供以后分析,它们以序列文件的形式写入_log/skip目录,可以用hadoop fs -text <filepath>解压并读取。你可以使用方法SkipBadRecords.setSkipOutputPath(JobConf conf, Path path)修改当前用于存放被跳过记录的目录_log/skip,如果path被设为空,或者一个值为“none”的字符串path,hadoop就会放弃记录被跳过的记录。
 
(2)在Java之外配置记录跳读
 
SkipBadRecords方法
JobConf属性
setAttemptsToStartSkipping() mapred.skip.attempts.to.start.skipping
setMapperMaxSkipRecords() mapred.skip.map.max.skip.records
setReducerMaxSkipGroups() mapred.skip.reduce.max.skip.groups
setSkipOutputPath() mapred.skip.out.dir
setAutoIncrMapperProcCount() mapred.skip.map.auto.incr.proc.count
setAutoIncrReducerProcCount() mapred.skip.reduce.auto.incr.proc.count
 
 
3、性能调优
 
(1)通过combiner来减少网络流量
     Combiner可以减少在map和reduce阶段之间洗牌的数据量,较低的网络流量缩短了执行时间。
 
(2)减少输入数据量
 
(3)使用压缩
     hadoop内置支持压缩与解压。启用对map输出的压缩涉及对两个属性的配置:
 
属性
描述
mapred.compress.map.output Boolean属性,表示mapper的输出是否被压缩
mapred.map.output.compression.codec Class属性,表示哪种CompressionCodec被用于压缩mapper的输出
 
conf.setBoolean(“mapred.compress.map.output”, true);
conf.setClass(“mapred.map.output.compression.codec”, GzipCodec.calss, CompressionCodec.class);
也可以直接使用JobConf中的便捷方法setCompressionMapOutput()和setMapOutputCompressorClass()。
 
(4)重用JVM
     hadoop从版本0.19.0开始,允许相同作业的多个任务之间重用JVM。因此,启动开销被平摊到多个任务中。一个新属性(mapred.job.reuse.jvm.num.tasks)指定了一个JVM可以运行的最大任务数。它默认值为1,此时JVM不能被重用。你可以增大该属性值来启用JVM重用。如果将其设置为-1,则意味着在可重复使用JVM的任务数量上没有限制。在JobConf对象中有一个便捷方法,setNumTasksToExecutePerJvm(int),可以用它很方便地设置作业的属性。
 
(5)根据猜测执行来运行
     启动和禁止猜测执行的配置属性:
 
属性
描述
mapred.map.tasks.speculative.execution 布尔属性,表示是否运行map任务猜测执行
mapred.reduce.tasks.speculative.execution 布尔属性,表示是否运行reduce任务猜测执行
 
(6)代码重构与算法重写
     Streaming程序重写为hadoop的Java程序
 
 
 [转载请注明] http://www.cnblogs.com/zhengrunjian/ 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

[Hadoop in Action] 第6章 编程实践的更多相关文章

  1. [Hadoop in Action] 第7章 细则手册

    向任务传递定制参数 获取任务待定的信息 生成多个输出 与关系数据库交互 让输出做全局排序   1.向任务传递作业定制的参数        在编写Mapper和Reducer时,通常会想让一些地方可以配 ...

  2. [hadoop in Action] 第3章 Hadoop组件

    管理HDFS中的文件 分析MapReduce框架中的组件 读写输入输出数据   1.HDFS文件操作   [命令行方式]   Hadoop的文件命令采取的形式为: hadoop fs -cmd < ...

  3. [Hadoop in Action] 第1章 Hadoop简介

    编写可扩展.分布式的数据密集型程序和基础知识 理解Hadoop和MapReduce 编写和运行一个基本的MapReduce程序   1.什么是Hadoop   Hadoop是一个开源的框架,可编写和运 ...

  4. [Hadoop in Action] 第5章 高阶MapReduce

    链接多个MapReduce作业 执行多个数据集的联结 生成Bloom filter   1.链接MapReduce作业   [顺序链接MapReduce作业]   mapreduce-1 | mapr ...

  5. [Hadoop in Action] 第4章 编写MapReduce基础程序

    基于hadoop的专利数据处理示例 MapReduce程序框架 用于计数统计的MapReduce基础程序 支持用脚本语言编写MapReduce程序的hadoop流式API 用于提升性能的Combine ...

  6. [Hadoop in Action] 第2章 初识Hadoop

    Hadoop的结构组成 安装Hadoop及其3种工作模式:单机.伪分布和全分布 用于监控Hadoop安装的Web工具   1.Hadoop的构造模块   (1)NameNode(名字节点)       ...

  7. 第二章 C语言编程实践

    上章回顾 宏定义特点和注意细节 条件编译特点和主要用处 文件包含的路径查询规则 C语言扩展宏定义的用法 第二章 第二章 C语言编程实践 C语言编程实践 预习检查 异或的运算符是什么 宏定义最主要的特点 ...

  8. [Java 并发] Java并发编程实践 思维导图 - 第一章 简单介绍

    阅读<Java并发编程实践>一书后整理的思维导图.

  9. [Java 并发] Java并发编程实践 思维导图 - 第二章 线程安全性

    依据<Java并发编程实践>一书整理的思维导图.

随机推荐

  1. Taurus.MVC 2.0 开源发布:WebAPI开发教程

    背景: 有用户反映,Tausus.MVC 能写WebAPI么? 能! 教程呢? 嗯,木有! 好吧,刚好2.0出来,就带上WEBAPI教程了! 开源地址: https://github.com/cyq1 ...

  2. ABP文档 - Javascript Api

    文档目录 本节内容: AJAX Notification Message UI Block & Busy Event Bus Logging Other Utility Functions A ...

  3. xamarin DependencyService源码阅读

    xamarin在面对PCL无法实现的各平台特有功能时使用了一种叫[DependencyService]的方式来实现.它使得xamarin能像原生平台一样做平台能做到的事情!主要分四个部分 接口:定义功 ...

  4. iOS开源项目周报0105

    由OpenDigg 出品的iOS开源项目周报第四期来啦.我们的iOS开源周报集合了OpenDigg一周来新收录的优质的iOS开发方面的开源项目,方便iOS开发人员便捷的找到自己需要的项目工具等. He ...

  5. 比Mysqli操作数据库更简便的方式 。PDO

    下面来说一下PDO 先画一张图来了解一下 mysqli是针对mysql这个数据库扩展的一个类 PDO是为了能访问更多数据库 如果出现程序需要访问其他数据库的话就可以用PDO来做 PDO数据访问抽象层1 ...

  6. Android消息传递之基于RxJava实现一个EventBus - RxBus

    前言: 上篇文章学习了Android事件总线管理开源框架EventBus,EventBus的出现大大降低了开发成本以及开发难度,今天我们就利用目前大红大紫的RxJava来实现一下类似EventBus事 ...

  7. 模拟AngularJS之依赖注入

    一.概述 AngularJS有一经典之处就是依赖注入,对于什么是依赖注入,熟悉spring的同学应该都非常了解了,但,对于前端而言,还是比较新颖的. 依赖注入,简而言之,就是解除硬编码,达到解偶的目的 ...

  8. PHP之购物车的代码

    该文章记录了购物车的实现代码,仅供参考 book_sc_fns.php <?php include_once('output_fns.php'); include_once('book_fns. ...

  9. H5项目开发分享——用Canvas合成文字

    以前曾用Canvas合成.裁剪.图片等<用H5中的Canvas等技术制作海报>.这次用Canvas来画文字. 下图中"老王考到驾照后"这几个字是画在Canvas上的,与 ...

  10. php批量删除

    php批量删除可以实现多条或者全部数据一起删除 新建php文件 显示数据库中内容: <table width="100%" border="1" cell ...