`

开发MapReduce常见问题

 
阅读更多

(1)当你把一个文件加入distribution cache的时候,要注意:如果你是以addCacheFile()的方式添加的,而你在mapper中取出来的时候,却是以archive的方式取出来——getLocalCacheArchives(),那么,你将得不到cache文件的路径,因为放进去和取出来的方式要一致。

(2)在mapper中获取当前正在处理的HDFS文件名/HDFS目录名

有时候,Hadoop是按行来对数据进行处理的,由于对每一行数据,map()函数会被调用一次,我们有时可以根据文件名/目录名来获取一些信息,从而把它们输出,例如,目录名中包含了日期,则我们可以取出来并输出到Reducer。在map()函数中,我们可以这样取文件名:

InputSplit inputSplit = context.getInputSplit();
String fileName = ((FileSplit) inputSplit).getName();
假设当前正在处理的HDFS文件路径为:/user/hadoop/abc/myFile.txt,则上面的 fileName 取到的是“myFile.txt”这样的字符串。但如果要获取其目录名“abc”,则可以这样做:

InputSplit inputSplit = context.getInputSplit();
String dirName = ((FileSplit) inputSplit).getPath().getParent().getName();

(5)从HDFS上下载同一目录下的一堆文件
如果是从HDFS上下载一个文件到本地文件系统,这样做:

hadoop fs -get /your/hdfs/file /your/local/fs/file
但如果是要下载一个目录下的N个M-R输出文件(到一个文件),则应这样:

hadoop fs -getmerge /your/hdfs/directory /your/local/fs/file
或者你干脆把HDFS上的文件内容打印出来,重定向到一个文件:

hadoop fs -cat /your/hdfs/directory/part* > /your/local/fs/file
(6)关于InputFormat
具体可看这个链接。这里摘抄一段下来:

The InputFormat defines how to read data from a file into the Mapper instances. Hadoop comes with several implementations of InputFormat; some work with text files and describe different ways in which the text files can be interpreted. Others, like SequenceFileInputFormat, are purpose-built for reading particular binary file formats. These types are described in more detail in Module 4.
More powerfully, you can define your own InputFormat implementations to format the input to your programs however you want. For example, the default TextInputFormat reads lines of text files. The key it emits for each record is the byte offset of the line read (as a LongWritable), and the value is the contents of the line up to the terminating '\n' character (as a Text object). If you have multi-line records each separated by a $ character, you could write your own InputFormat that parses files into records split on this character instead.
即:InputFormat定义了如何从文件中将数据读取到Mapper的实例里。Hadoop已经自带了一些InputFormat的实现了,其中有一些用于处理文本文件,它们描述了如何解释文本文件的多个不同方法;其他的实现——例如SequenceFileInputFormat——是为读取特殊二进制文件格式而生的。
更加强大的是,你可以定义你自己的InputFormat实现来格式化输入到你程序的数据——无论你想要什么样的输入。例如,默认的TextInputFormat读取文本文件的一行行的数据。它为每条记录emit的key是正在读取的行的偏移字节(以LongWritable的形式体现),而value则是该行的内容直到结束的 \n 字符(以Text对象的形式体现)。如果你有多行记录,这些记录是以 $ 字符来分隔的,那么你可以写一个自己的InputFormat用于根据这个字符来分割解析文件。

(7)为什么要启用LZO压缩,现在有什么可用的Hadoop LZO实现
这篇文章很好地解释了Twitter的Hadoop LZO实践,看完它,你就明白为什么要用LZO了。
这个项目,就是Twitter的Hadoop LZO实现,非常有用。
一句话总结就是:gzip不能将数据分块压缩,虽然减小了存储的数据量(同时也就减小了IO),但却无法利用Map-Reduce进行并行处理;bzip可以将数据分块压缩,虽然减小了存储的数据量(同时也就减小了IO),但是却在解压的时候很慢,耗费掉太多的CPU资源,从而导致CPU处理速度跟不上读取压缩文件的速度;LZO在这二者之间达到了一个平衡,虽然其压缩比没有gzip那么高,却可以分块压缩(从而可以利用Map-Reduce进行并行处理),并且其解压速度非常快,整体上达到的效果就是:减小了数据存储量,减小了IO,虽然CPU资源比原来占用多了一些,但是Hadoop集群整体上的计算能力提升了很多。

(8)启动Haoop进程时的错误及解决方法:localhost: ssh: connect to host localhost port 22: Connection refused
启动Hadoop进程时可用Hadoop安装目录下的 bin/start-all.sh 脚本,如果执行该脚本提示错误:

localhost: ssh: connect to host localhost port 22: Connection refused
那么你应该先检查你是否安装了sshd,然后再检查防火墙是否阻止了连接本机的22端口。依据不同的Linux发行版,这些检测方法会有不同。以Ubuntu为例,执行sshd命令,如果提示你sshd没有安装,那么你可以使用以下命令安装之:

sudo apt-get install openssh-server
检查防火墙状态:

sudo ufw status
如果防火墙是打开的,那么还要确保22端口是允许连接的。
可以在开机启动时就启动Hadoop进程:编辑 /etc/rc.local 文件,添加一行即可:

/usr/local/hadoop/bin/start-all.sh
当然,需视情况改成你的Hadoop安装路径。

(9)在 Hadoop Map/Reduce Administration 的web页面中看不到运行中的job(Running Jobs)的可能原因
可能是 TaskTracker 没有启动,导致无法在页面中看到任何Running Jobs。这时你可以先查看一下其是否启动了:

ps -ef | grep java
里面应该有 org.apache.hadoop.mapred.TaskTracker 这一项。
如果没有,则可以重启Hadoop进程试试看。

(10)向HDFS中put文件时揭示“Name node is in safe mode”的原因及解决办法
向HDFS中put文件时,如果揭示:

put: org.apache.Hadoop.hdfs.server.namenode.SafeModeException: Cannot create file /XXX. Name node is in safe mode.
原因很显然了,name node处于安全模式,解决办法也很简单:kill掉name node的进程,然后重启之:

ps -ef | grep java
用该命令查看name node进程的PID,然后kill掉,然后再启动之:

start-dfs.sh
再确定一下name node进程是否启动了,如果成功启动了,就OK了。

这里有一个批量kill进程的技巧,其实就是几句shell语句:

PIDS=`ps -ef | grep -v grep | grep java | awk '{print $2}'`; for PID in $PIDS; do kill $PID; done
其中,“grep java”表示查找含有“java”关键字的进程名,“grep -v grep”表示过滤掉grep自己的这个进程名,awk 是用于打印出第2列的内容,即PID(进程号),而后面的 for 循环则是批量kill掉找到的进程。

(11)在shell中判断一个HDFS目录/文件是否存在
直接看shell代码:

hadoop fs -test -e /hdfs_dir
if [ $? -ne 0 ]; then
    echo "Directory not exists!"
fi
hadoop fs -test -e 用于判断HDFS目录/文件是否存在,下一步检测该命令的返回值,以确定其判断结果。

-test -[ezd] <path>: If file { exists, has zero length, is a directory
then return 0, else return 1.
e,z,d参数必用其一,不可缺少。

(12)一次添加多个输入目录/文件到Map-Reduce job中
使用 FileInputFormat.addInputPaths(Job job, String commaSeparatedPaths) 方法,可以一次将多个目录/文件添加到M-R job中,其中,第二个参数是一个逗号分隔的路径列表,例如“/user/root/2012-01-01,/user/root/2012-01-02,/user/root/2012-01-03”。

(13)HBase中的TTL的单位
在hbase shell中,describe '表名'可以查看一个HBase表的结构和基本参数,例如:

hbase(main):005:0> describe 'TableName'
DESCRIPTION                                                             ENABLED                               
 {NAME => 'TableName', FAMILIES => [{NAME => 'fam', COMPRESSION = > 'NONE', VERSIONS => '2', TTL => '2147483647', BLOCKSIZE => '65536', IN_MEMORY => 'false', BLOCKCACHE => 'true'}]}
里面的TTL的单位是秒,不做特别设置的时候,就是这个默认值(约为69年),超过此时间的记录会被删除。

(14)HBase中的VERSIONS(版本)的含义
如上例所示,你已经看到了VERSIONS这个参数,假设其值为2,那么它表示:row key、column family、qualifier 都相同的记录最多可以有2条,这2条记录的timestamp不同。例如用hbase shell查到的下面两条记录:

abc     column=fam:\x11\x00\x00\x99, timestamp=1325260900000, value=?\x80\x00\x00
abc     column=fam:\x11\x00\x00\x99, timestamp=1326828800000, value=?\x80\x00\x00
其中,“abc”是row key,“fam”是column family,“\x11\x00\x00\x99”是qualifier,这三者均相同,而这两条记录的timestamp不同,也就是VERSIONS为2。

(15)context.progress()的作用
假设在map()方法中,你有一个从数据库读取大量数据的操作,是用一个循环来完成的,并且,在读完全部的数据之前,你不会有任何的数据输出(纯读),那么,读完全部数据所需的时间可能很长,一直没有输出的话,这个task就会因为超时被杀掉,为了避免这个问题,可在以读取数据的循环中使用context.progress()方法来报告进度,那么该task就会被认为还活着,从而解决超时问题。

(16)Map-Reduce的单元测试,用MRUnit来做
我们不可能把每个M-R job都放到到实际的环境中去运行,靠打印log来调试其中的问题,单元测试是必须的,M-R的单元测试用MRUnit来做。
①MRUnit有两个ReduceDriver,一个是 org.apache.hadoop.mrunit.mapreduce.ReduceDriver,另一个是 org.apache.hadoop.mrunit.ReduceDriver,其中,前者是为更新的Hadoop API准备的,如果你发现IDE在ReduceDriver这里提示错误,但是又不知道哪里写错了的时候,可以查看一下是否是这个问题。
②在测试一个mapper类中的时候,MRUnit的setUp()函数比mapper类的setup(Context context)函数要先执行。

(17)调用一个Java Map-Reduce程序时,在命令行传入参数“-D mapred.queue.name=XXX”的作用
Hadoop集群中的job被分在不同的队列中,如果不设置mapred.queue.name参数,则job被放置在默认队列中,否则就被放在指定的队列中。各队列之间是有优先级之分的,同一个队列中的各job也有优先级之分,所以,我们需要的话,可以既设置队列,又设置job的优先级:

-D mapred.queue.name=XXX
-D mapred.job.priority=HIGH
这表示设置优先级为HIGH。

(18)继承自org.apache.hadoop.hbase.mapreduce.TableMapper这个抽象类的一个mapper类,当它的map()方法每被调用一次时,就有HBase的一行(row)被读入处理,由于是处理一行,所以对一个map()方法来说,row key是唯一的,column family可能有N个,每个column family下又可能有M个qualifier,每一个qualifier还可能会对应X个timestamp的记录(取决于你HBase的VERSIONS设置),你可以在map()方法中,一级级地遍历得到所有记录。

(19)在大多数情况下,一个split里的数据(由一个mapper所处理)是来自于同一个文件的;少数情况下,一个split里的数据是来自多个文件的。

(20)org.apache.Hadoop.mapreduce.lib.output 和 org.apache.hadoop.mapreduce.output 这两个package都有 TextOutputFormat 类,其中,前者比后者版本新,使用的时候注意。

(21)执行Map-Reduce Java程序时,传入 -D hadoop.job.ugi=hadoop,hadoop 参数可以使得该job以hadoop用户来执行,例如,你是以Linux root用户来执行一个脚本,脚本中执行了一个M-R Java程序,那么该程序就无法将输出结果写入到HDFS上的 /user/hadoop/ 目录下,如果按上面的方法传入一个参数,就解决了这个问题:

hadoop com.codelast.DoSomething -D hadoop.job.ugi=hadoop,hadoop
其中,com.codelast.DoSomething是你的M-R Java程序。

(22)用MRUnit怎么测试含有FileSplit.getPath()的方法
如果mapper中的一个方法myMethod(Context context)含有如下代码片段:

String fileName = ((FileSplit) context.getInputSplit()).getPath().getName();
这句话是用来取当前mapper正在处理的文件名。那么,方法myMethod()就不能用MRUnit来测,因为无法使用MRUnit来设置mapper中当前正在处理的文件。为了测这个方法,你需要把上面的代码段抽取出来,单独放在一个方法中,我们假设其为:

public int getName(Context context) {
    return ((FileSplit) context.getInputSplit()).getPath().getName();
}
然后,在单元测试文件中,你的tester类里重写这个方法,自己指定一个返回值:

@Test
public void test_1() throws IOException {
 mapper = new MyMapper() {
   @Override
   public int getName(Context context) {
  return "part-r-00000";
   }
 };

 Configuration configuration = new Configuration();
 mapDriver.withConfiguration(configuration);
 mapDriver.withMapper(mapper);
 
 mapDriver.withInput(new LongWritable(1), new Text("XXXXXX"));
 //TODO:
}
其中,MyMapper是你的mapper类名,在这里我们强制指定了getName方法返回一个字段串“part-r-00000”,从而在下面的“//TODO:”测试代码中,就可以在调用待测的myMethod方法时(间接地会调用getName方法),自然会得到“part-r-00000”这个字符串。

(23)HBase中的Pair类
如果你只要保存一对对象,那么Map可能不好用,你可以用 org.apache.hadoop.hbase.util 包中的 Pair<T1, T2> 类:

Pair<String, String> aPair = new Pair<String, String>("abc", "def");
String firstStr = aPair.getFirst();
String secondStr = aPair.getSecond();
显然,getFirst()方法用于取第一个值,getScond()方法用于取第二个值。

(24)用MRUnit测试mapper时,如何避开从 DistributedCache 加载文件
可以在unit test里set一个值到 Configuration 对象中,在mapper里判断这个变量是否set了,set了就从用于测试的local file读数据,没有set就从DistributedCache读文件。

(25)只有map的job,如何在一定程度上控制map的数量
如果一个job只有map,那么,map的数量就是输出文件的数量,为了能减少输出文件的数量,可以采用减少map的数量的方法,那么,如何减少呢?其中一个办法是设置最小的input split size。例如以下代码:

FileInputFormat.setMinInputSplitSize(job, 2L * 1024 * 1024 * 1024);
将使得小于 2G 的输入文件不会被分割处理。如果你的输入文件中有很多都是小于2G的,并且你的Hadoop集群配置了一个split的大小是默认的64M,那么就会导致一个1点几G的文件就会被很多个map处理,从而导致输出文件数量很多。使用上面的方法设置了min input split size之后,减小输出文件数量的效果很明显。

(26)如何使用elephant-bird的 LzoTextOutputFormat 对纯文本数据进行LZO压缩
假设你有一堆纯文本数据,要将它们用LZO来压缩,那么,可以用elephant-bird的 LzoTextOutputFormat 来实现。
一个只有map的job就可以完成这个工作,你需要做的,首先是设置输出格式:

job.setMapperClass(MyMapper.class);
job.setOutputFormatClass(LzoTextOutputFormat.class);
其次,你需要这样的一个mapper类:

public static class MyMapper extends Mapper<LongWritable, Text, NullWritable, Text> {

  protected void map(LongWritable key, Text value, Context context) throws IOException, InterruptedException {
    context.write(null, value);
  }
}
其余代码此处省略。

(27)如何使MapReduce job执行开始时不检查某目录是否已经存在
如果M-R job的HDFS输出目录已经存在,那么job执行时会报错。为了让它不检查,或者改变默认的检查办法(例如,我们会在HDFS输出目录下生成几个子目录,在里面输出最终数据,只要确保这几个子目录不存在即可),那么就需要override checkOutputSpecs 这个方法:

  @Override
  public void checkOutputSpecs(JobContext job) throws IOException {
    //TODO:
  }
在这里面,你只要把exception吃掉即可使得输出目录存在时不会报错。

(28)使用HBase的程序报错“java.lang.NoSuchMethodError: org.apache.hadoop.hbase.client.HTable.<init>”的一个原因
如果你的程序使用了HBase,并且有HDFS操作(即使用了hadoop的jar包),那么出现上面所说的错误提示时,请检查Hadoop的安装路径下的lib目录下,HBase的jar包版本是否与你的程序路径下的HBase jar包版本相同,如果不同,那么就有可能导致这个问题。

分享到:
评论

相关推荐

    MapReduce技术流程介绍

    文档详细介绍了Mapreduce的开发流程,及开发过程中常见的一些问题,在我的编程过程中这些问题困扰了我很长时间,希望把它记录下来。

    java大数据内容_5Mapreduce、数据挖掘

    1 Mapreduce应用案例开发 1.1 常见运营案例 1.1.1 AccessLog AccessLog Nginx的access log: 201.158.69.116 - - [03/Jan/2013:21:17:20 -0600] fwf[-] tip[-] 127.0.0.1:9000 0.007 0.007 MX pythontab....

    大数据常见问题之数据倾斜.docx

    大数据常见问题之数据倾斜全文共5页,当前为第1页。大数据常见问题之数据倾斜全文共5页,当前为第1页。大数据常见问题之数据倾斜 大数据常见问题之数据倾斜全文共5页,当前为第1页。 大数据常见问题之数据倾斜全文共...

    创建MapReduce查询来处理特定类型的数据

    处理文本是MapReduce流程的一种常见用法,因为文本处理相对复杂且是处理器资源密集的处理。基本的字数统计常常用于演示 Haddoop处理大量文本和基本汇总大体内容的能力。要获得字数,将文本从一个输入文件中拆分...

    大数据常见问题之数据倾斜.pdf

    ⼤数据常见问题之数据倾斜 什么是数据倾斜 简单的讲,数据倾斜就是我们在计算数据的时候,数据的分散度不够,导致⼤量的数据集中到了⼀台或者⼏台机器上计算,这些数据的计 算速度远远低于平均计算速度,导致整个...

    Hadoop权威指南 中文版

    hadoop的i/o、mapreduce应用程序开发;mapreduce的工作机制:mapreduce的类型和格式;mapreduce的特性:如何安装hadoop集群,如何管理hadoop;pig简介:hbase简介:zookeeper简介,最后还提供了丰富的案例分析。  ...

    Hadoop: The Definitive Guide

    Hadoop的I/O、MapReduce应用程序开发;MapReduce的工作机制:MapReduce的类型和格式;MapReduce的特性:如何安装Hadoop集群,如何管理Hadoop;Pig简介:Hbase简介:ZooKeeper简介,最后还提供了丰富的案例分析。 ...

    Hadoop 权威指南(中文版)

    hadoop的i/o、mapreduce应用程序开发;mapreduce的工作机制:mapreduce的类型和格式;mapreduce的特性:如何安装hadoop集群,如何管理hadoop;pig简介:hbase简介:zookeeper简介,最后还提供了丰富的案例分析。 ...

    大数据开发面试题合集.pdf

    当应聘者面试大数据开发岗位时,以下是一些常见的面试题: - 1. 请解释一下什么是大数据(Big Data),并列举大数据的特征和应用场景。 - 2. 你熟悉的大数据技术栈有哪些?请简要介绍每种技术的作用和特点。 - 3. ...

    big-data:大数据要领

    第2周:使用MapReduce解决问题第3周:使用MapReduce解决问题(练习) 第4周:Apache Spark简介第5周:Apache Spark入门(练习) 第六周:实际应用网址:[讲座链接]( ) REF:[讲义]( ) 常见问题| 如何向教学人员...

    [Hadoop] 传智播客新版Hadoop视频教程 段海涛老师Hadoop八天完全攻克Hadoop视频教程 Hadoop开发

    有的人用这个骗钱,或者上传的都是残缺资源,我这...第四天 常见mr算法实现和shuffle的机制 第五天 hadoop2.x中HA机制的原理和全分布式集群安装部署及维护 第六天 hbase hive 第七天 storm+kafka 第八天 实战项目

    新版Hadoop视频教程 段海涛老师Hadoop八天完全攻克Hadoop视频教程 Hadoop开发

    第四天 常见mr算法实现和shuffle的机制 01-复习.avi 02-hadoop中的序列化机制.avi 03-流量求和mr程序开发.avi 04-hadoop的自定义排序实现.avi 05-mr程序中自定义分组的实现.avi 06-shuffle机制.avi 07-mr...

    Hive常用命令

    Hive是基于Hadoop的一个数据仓库工具,可以将结构化的数据文件映射为一张数据库... 其优点是学习成本低,可以通过类SQL 语句快速实现简单的MapReduce统计,不必开发专门的MapReduce应用,十分适合数据仓库的统计分析。

    大数据Spark企业级实战

    《大数据Spark企业级实战》详细解析了企业级Spark开发所需的几乎所有技术内容,涵盖Spark的架构设计、Spark的集群搭建、Spark内核的解析、Spark SQL、MLLib、GraphX、Spark Streaming、Tachyon、SparkR、Spark多语言...

    大数据学习计划.pdf

    其优点是学习成本低,⼤数据学习kou群74零零加【41三⼋yi】可以通过类SQL语句快速实现简单的 MapReduce统计,不必开发专门的MapReduce应⽤,⼗分适合数据仓库的统计分析。 本模块通过学习 Hive、Impala 等⼤数据 ...

    hadoop段海涛老师八天实战视频

    第一天 hadoop的基本概念 伪...第四天 常见mr算法实现和shuffle的机制 01-复习.avi 02-hadoop中的序列化机制.avi 03-流量求和mr程序开发.avi 04-hadoop的自定义排序实现.avi 05-mr程序中自定义分组的实现.avi

    ripley:项目提供处理语音和语音相关数据的工具

    ripley 语音工具库是对语音处理和识别社区中常见问题的探索。 考虑到有关不断增长的数据集的问题,该库的最初目标是利用开源语言建模工具包与 MapReduce?? 范式以启用 n-gram 语言模型的分布式训练。 这是开发调节...

    大数据培训课程安排.pdf

    HDFS界⾯、MR界⾯、简单的SHELL、java访问hadoop)、HDFS(简介、SHELL、IDEA开发⼯具使⽤、全分布式集群搭建)、 MapReduce应⽤(中间计算过程、Java操作MapReduce、程序运⾏、⽇志监控)、Hadoop⾼级应⽤(YARN框架介绍...

    kudu介绍及安装配置

    Kudu是一个针对ApacheHadoop平台而开发的列式存储管理器。Kudu共享Hadoop生态系统应用的常见技术特性:它在commodityhardware(商品硬件)上运行,horizontallyscalable(水平可扩展),并支持highlyavailable(高...

    大数据的一些面试题.pdf

    扩展: 问题实例:⽂档检索系统,查询那些⽂件包含了某单词,⽐如常见的学术论⽂的关键字搜索。 ⼋、外排序 适⽤范围:⼤数据的排序,去重 基本原理及要点:外排序的归并⽅法,置换选择败者树原理,最优归并树 扩展...

Global site tag (gtag.js) - Google Analytics