hadoop提交作业分析

hadoop提交作业分析
hadoop提交作业分析

Hadoop提交作业流程分析

bin/hadoop jar mainclass args ……

这样的命令,各位玩Hadoop的估计已经调用过NN次了,每次写好一个Project或对Project做修改后,都必须打个Jar包,然后再用上面的命令提交到Hadoop Cluster上去运行,在开发阶段那是极其繁琐的。程序员是“最懒”的,既然麻烦肯定是要想些法子减少无谓的键盘敲击,顺带延长键盘寿命。比如有的人就写了些Shell脚本来自动编译、打包,然后提交到Hadoop。但还是稍显麻烦,目前比较方便的方法就是用Hadoop eclipse plugin,可以浏览管理HDFS,自动创建MR程序的模板文件,最爽的就是直接Run on hadoop了,但版本有点跟不上Hadoop的主版本了,目前的MR模板还是的。还有一款叫Hadoop Studio的软件,看上去貌似是蛮强大,但是没试过,这里不做评论。那么它们是怎么做到不用上面那个命令来提交作业的呢不知道没关系,开源的嘛,不懂得就直接看源码分析,这就是开源软件的最大利处。

我们首先从bin/hadoop这个Shell脚本开始分析,看这个脚本内部到底做了什么,如何来提交Hadoop作业的。

因为是Java程序,这个脚本最终都是要调用Java来运行的,所以这个脚本最重要的就是添加一些前置参数,如CLASSPATH等。所以,我们直接跳到这个脚本的最后一行,看它到底添加了那些参数,然后再逐个分析(本文忽略了脚本中配置环境参数载入、Java查找、cygwin处理等的分析)。

#run it

exec "$JAVA"$JAVA_HEAP_MAX $HADOOP_OPTS -classpath "$CLASSPATH"$CLASS "$@"

从上面这行命令我们可以看到这个脚本最终添加了如下几个重要参数:JAVA_HEAP_MAX、HADOOP_OPTS、CLASSPATH、CLASS。下面我们来一个个的分析(本文基于Cloudera Hadoop 分析)。

首先是JAVA_HEAP_MAX,这个就比较简单了,主要涉及代码如下:

JAVA_HEAP_MAX=-Xmx1000m

# check envvars which might override default args

if [ "$HADOOP_HEAPSIZE" !="" ];then

#echo"run with heapsize $HADOOP_HEAPSIZE"

JAVA_HEAP_MAX="-Xmx""$HADOOP_HEAPSIZE""m"

#echo$JAVA_HEAP_MAX

fi

首先赋予默认值-Xmx1000m,然后检查中是否设置并导出了

HADOOP_HEAPSIZE,如果有的话,就使用该值覆盖,得到最后的JAVA_HEAP_MAX。

接着是分析CLASSPATH,这是这个脚本的重点之一。这部分主要就是添加了相应依赖库和配置文件到CLASSPATH。

# 首先用Hadoop的配置文件目录初始化CLASSPATH

CLASSPATH="${HADOOP_CONF_DIR}"

……

# 下面是针对于Hadoop发行版,添加Hadoop核心Jar包和webapps到CLASSPATH if [ -d "$HADOOP_HOME/webapps" ];then

CLASSPATH=${CLASSPATH}:$HADOOP_HOME

fi

for f in $HADOOP_HOME/hadoop-*;do

CLASSPATH=${CLASSPATH}:$f;

done

# 添加libs里的Jar包

for f in $HADOOP_HOME/lib/*.jar;do

CLASSPATH=${CLASSPATH}:$f;

Done

for f in $HADOOP_HOME/lib/*.jar;do

CLASSPATH=${CLASSPATH}:$f;

done

# 下面的TOOL_PATH只在命令为“archive”时才添加到CLASSPATH

for f in $HADOOP_HOME/hadoop-*;do

TOOL_PATH=${TOOL_PATH}:$f;

done

for f in $HADOOP_HOME/build/hadoop-*;do

TOOL_PATH=${TOOL_PATH}:$f;

done

# 最后添加用户的自定义Hadoop Classpath

if [ "$HADOOP_CLASSPATH" !="" ];then

CLASSPATH=${CLASSPATH}:${HADOOP_CLASSPATH}

fi

上面只分析一部分,由于代码比较长,针对开发者部分的CLASSPATH添加没有列出来。

下面是这个脚本的重点、实体之处:CLASS分析。Shell脚本会根据你输入的命令参数来设置CLASS和HADOOP_OPTS,其中CLASS所指向的类才是最终真正执行你的命令的实体。

# figure out which class to run

if [ "$COMMAND"="namenode" ] ;then

CLASS=''

HADOOP_OPTS="$HADOOP_OPTS $HADOOP_NAMENODE_OPTS"

……

elif [ "$COMMAND"="fs" ] ;then

CLASS=

HADOOP_OPTS="$HADOOP_OPTS $HADOOP_CLIENT_OPTS"

……

elif [ "$COMMAND"="jar" ] ;then

CLASS=

……

elif [ "$COMMAND"="archive" ] ;then

CLASS=

CLASSPATH=${CLASSPATH}:${TOOL_PATH}

HADOOP_OPTS="$HADOOP_OPTS $HADOOP_CLIENT_OPTS"

……

else

CLASS=$COMMAND

fi

这里我们要关心的就是"$COMMAND" = "jar"时对应的类,这个类等下我们继续分析,这是我们通向最终目标的下一个路口。

脚本在最后还设置了、等HADOOP_OPTS。接着,就利用exec命令带上刚才的参数提交任务了。

通过对上面的分析,我们知道了,如果想取代这个脚本,那就必须至少把Hadoop依赖的库和配置文件目录给加到CLASSPATH中(JAVA_HEAP_MAX和HADOOP_OPTS不是必须的),然后调用类来提交Jar到Hadoop。

PS:对Bash Shell不熟的可以先看看这我们分析了bin/hadoop脚本,知道了提交一个Hadoop作业所需要的基本设置以及真正执行任务提交的类。这一篇我们就来分析这个提交任务的类,看它内部具体又做了些什么。

RunJar是Hadoop中的一个工具类,结构很简单,只有两个方法:main和unJar。我们从main开始一步步分析。

main首先检查传递参数是否符合要求,然后从第一个传递参数中获取jar包的名字,并试图从jar中包中获取manifest信息,以查找mainclass name。如果查找不到mainclass name,则把传递参数中的第二个设为mainclass name。

接下去,就是在""下创建一个临时文件夹,并挂载上关闭删除线程。这个临时文件夹用来放置解压后的jar包内容。jar包的解压工作由unJar方法完成,通过JarEntry逐个获取jar包内的内容,包括文件夹和文件,然后释放到临时文件夹中。

解压完毕后,开始做classpath的添加,依次把解压临时文件夹、传递进来的jar包、临时文件夹内的classes文件夹和lib里的所有jar包加入到classpath 中。接着以这个classpath为搜索URL新建了一个URLClassLoader(要注意这个类加载器的parent包括了刚才bin/hadoop脚本提交时给的classpath),并设置为当前线程的上下文类加载器。

最后,利用方法,以刚才的那个URLClassLoader为类加载器,动态生成一个mainclass的Class对象,并获取它的main方法,然后以传递参数中剩下的参数作为调用参数来调用这个main方法。

好了,从上分析看来,这个RunJar类是一个很简单的类,就是解压传递进来的jar包,再添加一些classpath,然后动态调用jar包里的mainclass的main 方法。看到这里,我想你应该知道如何利用java代码来编写一个替代bin/hadoop 的程序了,主要就是两步:

添加Hadoop的依赖库和配置文件;

解压jar包,再添加一些classpath,并动态调用相应方法。最偷懒的方法,直接用RunJar类就行了。

通过前面两篇文章的分析,对Hadoop的作业提交流程基本明了了,下面我们就可以开始编写代码模拟这个流程。

第一步要做的是添加Hadoop的依赖库和配置文件到classpath。最常用的方法就是用一个容器先把各个要添加到classpath的文件或文件夹存储起来,后面再作为类加载器的URL搜索路径。

/**

* Add a directory or file to classpath.

*

* @param component

*/

publicstaticvoid addClasspath(String component) {

if ((component !=null) && () >0)) {

try {

File f =new File(component);

if ()) {

URL key = ().toURL();

if (!(key)) {

(key);

}

}

} catch (IOException e) {

}

}

}

上面的classPath变量就是我们声明用来装载classpath组件的容器。privatestatic ArrayList classPath =new ArrayList();

由于需要添加一些文件夹下的所有Jar包,所以我们还要实现一个遍历添加某文件夹下文件的方法。

/**

* Add all jars in directory to classpath, sub-directory is excluded. *

* @param dirPath

*/

public static void addJarsInDir(String dirPath) {

File dir =new File(dirPath);

if (!()) {

return;

}

File[] files = ();

if (files ==null) {

return;

}

for (int i =0; i < ; i++) {

if (files[i].isDirectory()) {

continue;

} else {

addClasspath(files[i].getAbsolutePath());

}

}

}

简单起见,这个方法没有使用Filter,对文件夹下的文件是通吃,也忽略掉了子文件夹,只处理根文件夹。

好了,有了基础方法,下面就是照着bin/hadoop中脚本所做的,把相应classpath添加进去。

/**

* Add default classpath listed in bin/hadoop bash.

*

* @param hadoopHome

*/

public static void addDefaultClasspath(String hadoopHome) { addClasspath(hadoopHome +"/conf");

addClasspath(hadoopHome +"/build/classes");

if (new File(hadoopHome +"/build/webapps").exists()) { addClasspath(hadoopHome +"/build");

}

addClasspath(hadoopHome +"/build/test/classes");

addClasspath(hadoopHome +"/build/tools");

if (new File(hadoopHome +"/webapps").exists()) {

addClasspath(hadoopHome);

}

addJarsInDir(hadoopHome);

addJarsInDir(hadoopHome +"/build");

addJarsInDir(hadoopHome +"/lib");

addJarsInDir(hadoopHome +"/lib/");

addJarsInDir(hadoopHome +"/build/ivy/lib/Hadoop/common");

}

至此,该添加classpath的都已添加好了(未包括第三方库,第三方库可用Conf中的tmpjars属性添加。),下去就是调用RunJar类了。本文为了方便,把RunJar中的两个方法提取了出来,去掉了一些可不要的Hadoop库依赖,然后整合到了类EJob里。主要改变是把原来解压Jar包的“文件夹改为"",并提取出了fullyDelete方法。

利用这个类来提交Hadoop作业很简单,下面是一个示例:

args =new String[4];

args[0] ="E:\\Research\\Hadoop\\";

args[1] ="pi";

args[2] ="2";

args[3] ="100";

ar mainclass args命令类似,但是忽略掉了bin/hadoop jar这个命令,因为我们现在不需要这个脚本来提交作业了。新建一个Project,添加一个class,在main里粘上上面的代码,然后Run as Java Application。注意看你的Console,你会发现你已经成功把作业提交到Hadoop上去了。

有图有真相,粘一下我的运行示例(在Win上开Eclipse,Hadoop Cluster 在Linux,配置文件同Cluster的一样)。

下面是在Cloudera Desktop看到的Job信息(它的时间是UTC的)。

用上述方法,我们可以做一个类似Cloudera Desktop的Web应用,接受用户提交的Jar,并在Action处理中提交到Hadoop中去运行,然后把结果返回给用户。

由于篇幅原因,加上前面介绍过RunJar类,所本文没有粘关于RunJar类的代码,不过你放心,本文提供例子工程下载。你可以在此基础上优化它,添加更多功能。由于大部分是Hadoop的代码,So,该代码基于Apache License。

-->>点我下载<<--

到此,以Java方式提交Hadoop作业介绍完毕。但,是否还可以再进一步呢现在还只能提交打包好的MR程序,尚不能像Hadoop Eclipse Plugin那样能直接对包含Mapper和Reducer的类Run on Hadoop。为什么直接对这些类Run as Java Application提交的作业是在Local运行的呢这其中又包含有什么秘密呢我们将在下面的文章中更深入的剖析Hadoop的作业提交代码,去到最底层,慢慢揭开它的黑面纱。

前面我们所分析的部分其实只是Hadoop作业提交的前奏曲,真正的作业提交代码是在MR程序的main里,RunJar在最后会动态调用这个main,在(二)里有说明。我们下面要做的就是要比RunJar更进一步,让作业提交能在编码时就可实现,就像Hadoop Eclipse Plugin那样可以对包含Mapper和Reducer的MR类直接Run on Hadoop。

一般来说,每个MR程序都会有这么一段类似的作业提交代码,这里拿WordCount的举例:

Configuration conf =new Configuration();

String[] otherArgs =new GenericOptionsParser(conf,

args).getRemainingArgs();

if !=2) {

"Usage: wordcount ");

(2);

}

Job job =new Job(conf, "word count");

;

;

;

;

;

;

(job, new Path(otherArgs[0]));

(job, new Path(otherArgs[1]));

(true) 0 : 1);

首先要做的是构建一个Configuration对象,并进行参数解析。接着构建提交作业用的Job对象,并设置作业Jar包、对应Mapper和Reducer类、输入输出的Key和Value的类及作业的输入和输出路径,最后就是提交作业并等待作业结束。这些只是比较基本的设置参数,实际还支持更多的设置参数,这里就不一一介绍,详细的可参考API文档。

一般分析代码都从开始一步步分析,但我们的重点是分析提交过程中发生的事,这里我们先不理前面的设置对后面作业的影响,我们直接跳到作业提交那一步进行分析,当碰到问题需要分析前面的代码时我会再分析。

当调用时,其内部调用的是submit方法来提交,如果传入参数为ture则及时打印作业运作信息,否则只是等待作业结束。submit方法进去后,还有一层,里面用到了job对象内部的jobClient对象的submitJobInternal来提交作业,从这个方法才开始做正事。进去第一件事就是获取jobId,用到了jobSubmitClient对象,jobSubmitClient对应的类是JobSubmissionProtocol 的实现之一(目前有两个实现,JobTracker和LocalJobRunner),由此可判断出jobSubmitClient对应的类要么是JobTracker,要么是LocalJobRunner。呃,这下有点想法了,作业提交是上到JobTracker去,还是在本地执行可能就是看这个jobSunmitClient初始化时得到的是哪个类的实例了,我们可以稍稍的先往后看看,你会发现submitJobInternal最后用了(jobId)来提交作业,再稍稍看看JobTracker和LocalJobRunner的submitJob实现,看来确实是这么回事。好,那我们就先跳回去看看这个jobSubmitClient是如何初始化的。在JobClient

的init中我们可以发现jobSubmitClient的初始化语句:

String tracker = ("", "local");

if ("local".equals(tracker)) {

=new LocalJobRunner(conf);

} else {

= createRPCProxy(conf), conf);

}

哈,跟conf中的属性有关,如果你没设置,那默认得到的值就是local,jobSubmitClient也就会被赋予LocalJobRunner的实例。平时,我们开发时一般都只是引用lib里面的库,不引用conf文件夹里的配置文件,这里就能解释为什么我们直接Run as Java Application时,作业被提交到Local去运行了,而不是Hadoop Cluster中。那我们把conf文件夹添加到classpath,就能Run on Hadoop了么目前下结论尚早,我们继续分析(你添加了conf文件夹后,可以提交试一试,会爆出一个很明显的让你知道还差什么的错误,这里我就卖卖官子,先不说)。

jobId获取到后,在SystemDir基础上加jobId构建了提交作业的目录submitJobDir,SystemDir由JobClient的getSystemDir方法得出,这个SystemDir在构建fs对象时很重要,确定了返回的fs的类型。下去的configureCommandLineOptions方法主要是把作业依赖的第三方库或文件上传

到fs中,并做classpath映射或Symlink,以及一些参数设置,都是些细微活,这里不仔细分析。我们主要关心里面的两个地方,一个是:

FileSystem fs = getFs();

看上去很简单,一句话,就是获取FileSystem的实例,但其实里面绕来绕去,有点头晕。因为Hadoop对文件系统进行了抽象,所以这里获得fs实例的类型决定了你是在hdfs上操作还是在local fs上操作。好了,我们冲进去看看。

publicsynchronized FileSystem getFs() throws IOException {

if ==null) {

Path sysDir = getSystemDir();

= (getConf());

}

return fs;

}

看见了吧,fs是由sysDir的getFileSystem返回的。我们再冲,由于篇幅,下面就只列出主要涉及的语句。

(), conf);

(uri, conf);

fs = createFileSystem(uri, conf);

Class<> clazz = ("fs."+ () +".impl", null);

if (clazz ==null) {

thrownew IOException("No FileSystem for scheme: "+ ());

}

FileSystem fs = (FileSystem)(clazz, conf);

(uri, conf);

return fs;

又是跟conf有关,看来conf是得实时跟住的。这里用到了Java的反射技术,用来动态生成相应的类实例。其中的class获取与有密切关系,而uri就是在刚才的sysDir基础上构成,sysDir的值又最终是由jobSubmitClient的实例决定的。如果jobSubmitClient是JobTracker的实例,那Scheme就是hdfs。如果是LocalJobRunner的实例,那就是file。从你可以找到如下的信息:

The FileSystem for file: uris.

The FileSystem for hdfs: uris.

所以在前面的作业提交代码中,在初始化Job实例时,很多事已经决定了,由conf文件夹中的配置文件决定。Configuration是通过当前线程上下文的类加载器来加载类和资源文件的,所以要想Run on Hadoop,第一步必须要让Conf

文件夹进入Configuration的类加载器的搜索路径中,也就是当前线程上下文的类加载器。

第二个要注意的地方是:

String originalJarPath = ();

if (originalJarPath !=null) {

if ("".equals())){

(new Path(originalJarPath).getName());

}

());

(new Path(originalJarPath), submitJarFile);

(submitJarFile, replication);

(submitJarFile, new FsPermission(JOB_FILE_PERMISSION));

} else {

("No job jar file set. User classes may not be found. "+

"See JobConf(Class) or JobConf#setJar(String).");

}

因为client在提交作业到Hadoop时需要把作业打包成jar,然后copy到fs的submitJarFile路径中。如果我们想Run on Hadoop,那就必须自己把作业

的class文件打个jar包,然后再提交。在Eclipse中,这就比较容易了。这里假设你启用了自动编译功能。我们可以在代码的开始阶段加入一段代码用来打包bin文件夹里的class文件为一个jar包,然后再执行后面的常规操作。

在configureCommandLineOptions方法之后,submitJobInternal会检查输出文件夹是否已存在,如果存在则抛出异常。之后,就开始划分作业数据,并根据split数得到map tasks的数量。最后,就是把作业配置文件写入submitJobFile,并调用(jobId)最终提交作业。

至此,对Hadoop的作业提交分析也差不多了,有些地方讲的比较啰嗦,有些又讲得点到而止,但大体的过程以及一些较重要的东西还是说清楚了,其实就是那么回事。下去的文章我们会在前面的jobUtil基础上增加一些功能来支持Run on Hadoop,其实主要就是增加一个打包Jar的方法。

经过上一篇的分析,我们知道了Hadoop的作业提交目标是Cluster还是Local,与conf文件夹内的配置文件参数有着密切关系,不仅如此,其它的很多类都跟conf有关,所以提交作业时切记把conf放到你的classpath中。

因为Configuration是利用当前线程上下文的类加载器来加载资源和文件的,所以这里我们采用动态载入的方式,先添加好对应的依赖库和资源,然后再构建一个URLClassLoader作为当前线程上下文的类加载器。

publicstatic ClassLoader getClassLoader() {

ClassLoader parent = ().getContextClassLoader();

if (parent ==null) {

parent =

}

if (parent ==null) {

parent = ();

}

return new URLClassLoader(new URL[0]), parent);

}

代码很简单,废话就不多说了。调用例子如下:

("/usr/lib/conf");

ClassLoader classLoader = ();

().setContextClassLoader(classLoader);

设置好了类加载器,下面还有一步就是要打包Jar文件,就是让Project

自打包自己的class为一个Jar包,我这里以标准Eclipse工程文件夹布局为例,打包的就是bin文件夹里的class。

public static File createTempJar(String root) throws IOException {

if (!new File(root).exists()) {

returnnull;

}

Manifest manifest =new Manifest();

().putValue("Manifest-Version", "");

final File jarFile = ("EJob-", ".jar", new File("")));

().addShutdownHook(new Thread() {

publicvoid run() {

();

}

});

JarOutputStream out =new JarOutputStream(new FileOutputStream(jarFile), manifest);

createTempJarInner(out, new File(root), "");

();

();

return jarFile;

}

private static void createTempJarInner(JarOutputStream out, File f,

hadoop基本操作指令

Hadoop基本操作指令 假设Hadoop的安装目录HADOOP_HOME为/home/admin/hadoop,默认认为Hadoop环境已经由运维人员配置好直接可以使用 启动与关闭 启动Hadoop 1. 进入HADOOP_HOME目录。 2. 执行sh bin/start-all.sh 关闭Hadoop 1. 进入HADOOP_HOME目录。 2. 执行sh bin/stop-all.sh 文件操作 Hadoop使用的是HDFS,能够实现的功能和我们使用的磁盘系统类似。并且支持通配符,如*。 查看文件列表 查看hdfs中/user/admin/aaron目录下的文件。 1. 进入HADOOP_HOME目录。 2. 执行sh bin/hadoop fs -ls /user/admin/aaron 这样,我们就找到了hdfs中/user/admin/aaron目录下的文件了。 我们也可以列出hdfs中/user/admin/aaron目录下的所有文件(包括子目录下的文件)。 1. 进入HADOOP_HOME目录。 2. 执行sh bin/hadoop fs -lsr /user/admin/aaron 创建文件目录 查看hdfs中/user/admin/aaron目录下再新建一个叫做newDir的新目录。 1. 进入HADOOP_HOME目录。 2. 执行sh bin/hadoop fs -mkdir /user/admin/aaron/newDir 删除文件 删除hdfs中/user/admin/aaron目录下一个名叫needDelete的文件 1. 进入HADOOP_HOME目录。 2. 执行sh bin/hadoop fs -rm /user/admin/aaron/needDelete 删除hdfs中/user/admin/aaron目录以及该目录下的所有文件

Hadoop 学习笔记

Hadoop 在Hadoop上运行MapReduce命令 实验jar:WordCount.jar 运行代码:root/……/hadoop/bin/hadoop jar jar包名称使用的包名称input(输入地址) output(输出地址) 生成测试文件:echo -e "aa\tbb \tcc\nbb\tcc\tdd" > ceshi.txt 输入地址:/data2/u_lx_data/qiandongjun/eclipse/crjworkspace/input 输出地址:/data2/u_lx_data/qiandongjun/eclipse/crjworkspace/output 将测试文件转入输入文件夹:Hadoop fs -put ceshi.txt /data2/u_lx_data/qiandongjun/eclipse/crjworkspace/input/ceshi.txt 运行如下代码:hadoop jar /data2/u_lx_data/qiandongjun/eclipse/crjworkspace/WordCount.jar WordCount /data2/u_lx_data/qiandongjun/eclipse/crjworkspace/input/ceshi.txt /data2/u_lx_data/qiandongjun/eclipse/crjworkspace/output Hadoop架构 1、HDFS架构 2、MapReduce架构 HDFS架构(采用了Master/Slave 架构) 1、Client --- 文件系统接口,给用户调用 2、NameNode --- 管理HDFS的目录树和相关的的文件元数据信息以及监控DataNode的状 态。信息以“fsimage”及“editlog”两个文件形势存放 3、DataNode --- 负责实际的数据存储,并将数据定期汇报给NameNode。每个节点上都 安装一个DataNode 4、Secondary NameNode --- 定期合并fsimage和edits日志,并传输给NameNode (存储基本单位为block) MapReduce架构(采用了Master/Slave 架构) 1、Client --- 提交MapReduce 程序并可查看作业运行状态 2、JobTracker --- 资源监控和作业调度 3、TaskTracker --- 向JobTracker汇报作业运行情况和资源使用情况(周期性),并同时接 收命令执行操作 4、Task --- (1)Map Task (2)Reduce Task ——均有TaskTracker启动 MapReduce处理单位为split,是一个逻辑概念 split的多少决定了Map Task的数目,每个split交由一个Map Task处理 Hadoop MapReduce作业流程及生命周期 一共5个步骤 1、作业提交及初始化。JobClient将作业相关上传到HDFS上,然后通过RPC通知JobTracker,

(完整版)hadoop例题

选择题 1、关于MapReduce的描述错误的是() A、MapReduce框架会先排序map任务的输出 B、通常,作业的输入输出都会被存储在文件系统中 C、通常计算节点和存储节点是同一节点 D、一个Task通常会把输入集切分成若干独立的数据块 2、关于基于Hadoop的MapReduce编程的环境配置,下面哪一步是不必要的() A、安装linux或者在Windows下安装Cgywin B、安装java C、安装MapReduce D、配置Hadoop参数 3、关于基于Hadoop的MapReduce编程的环境配置,下面哪一步是不必要的() A、配置java环境变量 B、配置Hadoop环境变量 C、配置Eclipse D、配置ssh 4、下列说法错误的是() A、MapReduce中maperconbiner reducer 缺一不可 B、在JobConf中InputFormat参数可以不设 C、在JobConf中MapperClass参数可以不设

D、在JobConf中OutputKeyComparator参数可以不设 5、下列关于mapreduce的key/value对的说法正确的是() A、输入键值对不需要和输出键值对类型一致 B、输入的key类型必须和输出的key类型一致 C、输入的value类型必须和输出的value类型一致 D、输入键值对只能映射成一个输出键值对 6、在mapreduce任务中,下列哪一项会由hadoop系统自动排序() A、keys of mapper's output B、values of mapper's output C、keys of reducer's output D、values of reducer's output 7、关于mapreduce框架中一个作业的reduce任务的数目,下列说法正确的是() A、由自定义的Partitioner来确定 B、是分块的总数目一半 C、可以由用户来自定义,通过JobConf.setNumReducetTask(int)来设定一个作业中reduce的任务数目 D、由MapReduce随机确定其数目 8、MapReduce框架中,在Map和Reduce之间的combiner的作用是() A、对Map的输出结果排序 B、对中间过程的输出进行本地的聚集

hadoop常用命令

启动Hadoop ?进入HADOOP_HOME目录。 ?执行sh bin/start-all.sh 关闭Hadoop ?进入HADOOP_HOME目录。 ?执行sh bin/stop-all.sh 1、查看指定目录下内容 hadoopdfs –ls [文件目录] eg: hadoopdfs –ls /user/wangkai.pt 2、打开某个已存在文件 hadoopdfs –cat [file_path] eg:hadoopdfs -cat /user/wangkai.pt/data.txt 3、将本地文件存储至hadoop hadoopfs –put [本地地址] [hadoop目录] hadoopfs –put /home/t/file.txt /user/t (file.txt是文件名) 4、将本地文件夹存储至hadoop hadoopfs –put [本地目录] [hadoop目录] hadoopfs –put /home/t/dir_name /user/t (dir_name是文件夹名) 5、将hadoop上某个文件down至本地已有目录下hadoopfs -get [文件目录] [本地目录] hadoopfs –get /user/t/ok.txt /home/t 6、删除hadoop上指定文件 hadoopfs –rm [文件地址] hadoopfs –rm /user/t/ok.txt 7、删除hadoop上指定文件夹(包含子目录等)hadoopfs –rm [目录地址] hadoopfs –rmr /user/t

8、在hadoop指定目录内创建新目录 hadoopfs –mkdir /user/t 9、在hadoop指定目录下新建一个空文件 使用touchz命令: hadoop fs -touchz /user/new.txt 10、将hadoop上某个文件重命名 使用mv命令: hadoop fs –mv /user/test.txt /user/ok.txt (将test.txt重命名为ok.txt) 11、将hadoop指定目录下所有内容保存为一个文件,同时down至本地hadoopdfs –getmerge /user /home/t 12、将正在运行的hadoop作业kill掉 hadoop job –kill [job-id] 1、列出所有Hadoop Shell支持的命令 $ bin/hadoopfs -help 2、显示关于某个命令的详细信息 $ bin/hadoopfs -help command-name 3、用户可使用以下命令在指定路径下查看历史日志汇总 $ bin/hadoop job -history output-dir 这条命令会显示作业的细节信息,失败和终止的任务细节。 4、关于作业的更多细节,比如成功的任务,以及对每个任务的所做的尝试次数等可以用下面的命令查看 $ bin/hadoop job -history all output-dir 5、格式化一个新的分布式文件系统: $ bin/hadoopnamenode -format 6、在分配的NameNode上,运行下面的命令启动HDFS: $ bin/start-dfs.sh bin/start-dfs.sh脚本会参照NameNode上${HADOOP_CONF_DIR}/slaves文件的内容,在所有列出的slave上启动DataNode守护进程。 7、在分配的JobTracker上,运行下面的命令启动Map/Reduce: $ bin/start-mapred.sh bin/start-mapred.sh脚本会参照JobTracker上${HADOOP_CONF_DIR}/slaves文件的内容,在所有列出的slave上启动TaskTracker守护进程。 8、在分配的NameNode上,执行下面的命令停止HDFS: $ bin/stop-dfs.sh

hadoop提交作业分析

Hadoop提交作业流程分析 bin/hadoop jar mainclass args …… 这样的命令,各位玩Hadoop的估计已经调用过NN次了,每次写好一个Project或对Project做修改后,都必须打个Jar包,然后再用上面的命令提交到Hadoop Cluster上去运行,在开发阶段那是极其繁琐的。程序员是“最懒”的,既然麻烦肯定是要想些法子减少无谓的键盘敲击,顺带延长键盘寿命。比如有的人就写了些Shell脚本来自动编译、打包,然后提交到Hadoop。但还是稍显麻烦,目前比较方便的方法就是用Hadoop eclipse plugin,可以浏览管理HDFS,自动创建MR程序的模板文件,最爽的就是直接Run on hadoop了,但版本有点跟不上Hadoop的主版本了,目前的MR模板还是的。还有一款叫Hadoop Studio的软件,看上去貌似是蛮强大,但是没试过,这里不做评论。那么它们是怎么做到不用上面那个命令来提交作业的呢不知道没关系,开源的嘛,不懂得就直接看源码分析,这就是开源软件的最大利处。 我们首先从bin/hadoop这个Shell脚本开始分析,看这个脚本内部到底做了什么,如何来提交Hadoop作业的。 因为是Java程序,这个脚本最终都是要调用Java来运行的,所以这个脚本最重要的就是添加一些前置参数,如CLASSPATH等。所以,我们直接跳到这个脚本的最后一行,看它到底添加了那些参数,然后再

逐个分析(本文忽略了脚本中配置环境参数载入、Java查找、cygwin 处理等的分析)。 #run it exec "$JAVA"$JAVA_HEAP_MAX $HADOOP_OPTS -classpath "$CLASSPATH"$CLASS "$@" 从上面这行命令我们可以看到这个脚本最终添加了如下几个重要参数:JAVA_HEAP_MAX、HADOOP_OPTS、CLASSPATH、CLASS。下面我们来一个个的分析(本文基于Cloudera Hadoop 分析)。 首先是JAVA_HEAP_MAX,这个就比较简单了,主要涉及代码如下:JAVA_HEAP_MAX=-Xmx1000m # check envvars which might override default args if [ "$HADOOP_HEAPSIZE" !="" ];then #echo"run with heapsize $HADOOP_HEAPSIZE" JAVA_HEAP_MAX="-Xmx""$HADOOP_HEAPSIZE""m" #echo$JAVA_HEAP_MAX fi

Hadoop入门教程(四)MR作业的提交监控、输入输出控制及特性使用-北京尚学堂

北京尚学堂提供 上次课讲到MR重要运行参数,本次继续为大家讲解MapReduce相关 提交作业并监控 JobClient是用户作业与JobTracker交互的主要接口,它提供了提交作业,跟踪作业进度、访问任务报告及logs、以及获取MR集群状态信息等方法。 提交作业流程包括: ?检查作业的输入输出 ?计算作业的输入分片(InputSplit) ?如果需要,为DistributedCache设置必须的账户信息 ?将作业用到的jar包文件和配置信息拷贝至文件系统(一般为HDFS)上的MR系统路径中 ?提交作业到JobTracker,并可监控作业状态 作业历史(Job History)文件会记录在https://www.360docs.net/doc/8713503111.html,er.location指定的位置,默认在作业输出路径下的logs/history/路径下。因此历史日志默认在mapred.output.dir/logs/history下。 用户可以将https://www.360docs.net/doc/8713503111.html,er.location值设置为none来不记录作业历史。 使用命令来查看历史日志: 1 $hadoop job -history output-dir 上面命令会显示作业的详细信息、失败的被kill的任务(tip)的详细信息。使用下面命令可以查看作业更详细的信息: 1 $hadoop job -history all output-dir 可以使用OutputLogFilter从输出路径中过滤日志文件。 一般,我们创建应用,通过JobConf设置作业的各种属性,然后使用JobClient提交作业并监控进度。 作业控制 有时可能需要一个作业链完成复杂的任务。这点是可以轻松实现的,因为作业输出一般都在分布式文件系统上,作业输出可以当做下个作业的输入,这样就形成了链式作业。 这种作业成功是否依赖于客户端。客户端可以使用以下方式来控制作业的执行: ?runJob(JobConf):提交作业并仅在作业完成时返回 ?submitJob(JobConf):提交作业后立即返回一个RunningJob的引用,使用它可以查询作业状态并处理调度逻辑。 ?JobConf.setJobEndNotificationURI(String):设置作业完成时通知 你也可以使用Oozie来实现复杂的作业链。 作业输入 下面讲作业输入的内容。 InputFormat描述MR作业的输入信息。InputFormat有以下作用: 1.验证作业的输入信息

基于Hadoop的数据作业管理平台设计与实现

基于Hadoop的数据作业管理平台设计与实现随着“大数据”时代的到来,分布式数据处理平台受到越来越广泛的关注,其中H adoop成为了以数据为中心的大规模数据处理平台的主流实现之一。Hadoop在互联网企业得到了广泛的应用,由于Hadoop任务处理需要编写MapReduce程序、处理数据的输入和输出,并且在大公司内每天的任务处理数量庞大,如何对Hadoop的任务进行有效管理成为了一大难点。因此开发一套基于Hadoop的数据作业管理平台显得十分有必要。本文首先详细分析了Hadoop的分布式文件系统和MapReduce计算框架,最后详细阐述了平台的设计和实现。 本文完成的主要工作包括:1.在充分考虑通用性、扩展性、安全性以及高效性的基础上确定了平台架构,规划了基于Hadoop的数据作业管理平台的框架设计,基于Nginx、FastGCI、MFC等技术设计了平台的逻辑功能模块、数据库结构和客户端界面。2.基于Hadoop的分布式文件系统(HDFS),实现了业务数据的分布式存储;基于Hadoop的MapReduce编程模型对平台的分布处理程序进行了封装,实现了Hadoop任务的统一调度。3.规划了图片批次数据从批次创建、数据准备、批次作业、批次验收到批次入库的处理流程,实现了业务流程的平台化管理。4.建立了平台的帐号管理体系,对帐号进行角色权限管理,实现了不同模块间的权限分离,保证了平台的数据安全性。 本文设计和实现的基于Hadoop的数据的数据作业管理平台已经在某企业投入使用。平台结合Hadoop分布式处理系统,支持图片业务数据的分布式存储、图片拼接分布式处理和图片隐私打码分布式处理,实现了图片业务数据的流程化处理。平台运行以来稳定可靠,缩短了业务数据的作业周期,减少了人力成本,达到了预期设计目标。

Hadoop原理期末作业(5)

Hadoop原理期末作业 一、搭建一个由三个节点构成的完全分布式非HA集群; 1、主机角色分配: 2、搭建HDFS集群: (1)core-site.xml配置文件代码及注释所编辑的代码行作用:(5分) fs.defaultFS hdfs://JYM2018122101001Master:9000 (2)hadoop-env.sh配置文件代码及注释所编辑的代码行作用:(5分) export JAVA_HOME=/home/YM/software/jdk1.8.0_45 (3)hdfs-site.xml配置文件代码及注释所编辑的代码行作用:(5分) https://www.360docs.net/doc/8713503111.html,.dir /home/YM/dfsdate/name dfs.datanode.data.dir /home/YM/dfsdate/data

https://www.360docs.net/doc/8713503111.html,node.secondary.http-address JYM2018122101001Slave01:50090 dfs.replication 2 dfs.blocksize 128M (4)slaves配置文件代码:(1分) JYM2018122101001Slave01 JYM2018122101001Slave02 (5)将Hadoop配置到/etc/profile系统环境变量;(2分) export JAVA_HOME=/home/YM/software/jdk1.8.0_45 export JRE_HOME=/home/YM/software/jdk1.8.0_45/jre export CLASSPATH=$JAVA_HOME/lib/dt.jar:$JAVA_HOME/lib/tools.jar:$JRE_HOME/lib export HADOOP_HOME=/home/YM/software/hadoop-2.8.1 export PATH=$PATH:$JAVA_HOME/bin:$HADOOP_HOME/bin:$HADOOP_HOME/sbin (6)批量启动HDFS集群,查看各个节点的进程,并截图,要求截图中必须含有用户及主机名;(5分) 2、搭建简单yarn集群: (1)yarn-site.xml配置文件的内容及注释所编辑的代码行作用;(5分)

Hadoop期末整理

(一) 1、凡是数据量超过一定大小,导致常规软件无法在一个可接受的时间范围内完成对其进行抓取、管理和处理工作的数据即可称为大数据。 2、四个特征:体量、多样性、价值密度、速度 3、3个维度对大数据进行分析:数据量大小、数据类型、数据时效性 4、数据处理平台的基础架构6个主要的基本组件:数据集成、文件存储、数据存储、数据计算、数据分析、平台管理。 5、可以归纳为三类问题:大数据存储、高性能计算和系统容错性 1、Hadoop的核心由3个子项目组成:Hadoop Common、HDFS、MapReduce (二) 2、HDFS组件: https://www.360docs.net/doc/8713503111.html,Node:是HDFS系统中的管理者,它负责管理文件系统的命名空间,维护文件系统的文件树及所有的文件和目录的元数据。 2.Secondary NameNode:在一个Hadoop集群环境中,只有一个NameNode节点,它是整个系统的关键故障点。为了避免NameNode节点发生故障影响整个系统的运行,因此设计了Secondary NameNode节点,它一般在一台单独的物理计算机上运行,与NameNode保持通信,按照一点时间间隔保持文件系统元数据的快照。 3.DateNode:是HDFS文件系统中保存数据的节点。 3、MapReduce组件:JobClient:是基于MapReduce借口库编写的客户端程序,负责提交MapReduce作业。JobTracker:是应用于MapReduce模块之间的控制协调者,负责协调MapReduce作业的执行。TaskTracker:负责执行由JobTracker分配的任务,每个TaskTracker 可以启动一个或多个Map或Reduce任务。MapTask、ReduceTask:是由TaskTracker启动的负责具体执行Map或Reduce任务的程序。 4、Hadoop相关技术及简介(主要)1.Hadoop Common:为Hadoop整体架构提供基础支撑性功能。2.Hadoop Distributed File System(HDFS):是一个适合构建于廉价计算机集群之上的分布式文件系统,具有低成本、高可靠性、高吞吐量的特点。3.Hadoop MapReduce:是一个编程模型和软件框架,用于在大规模计算机集群上编写对大数据进行快速处理的并行化程序。4.Hadoop Database(HBase):是一个分布式的、面向列的开源数据库,不同于一般的关系数据库,它是一个适合于非结构化大数据存储的数据库。5.Hive:是一个基于Hadoop的数据仓库工具,它可以将结构化的数据文件映射为一张数据库表,并提供强大的类SQL查询功能,可以将SQL语句转换为MapReduce任务进行运行。6.Sqoop:是一款用于在Hadoop 系统与传统数据库间进行数据交换的工具,可以用于将传统数据库中的数据导入HDFS或MapReduce,并将处理后的结果导出到传统数据库中。7.ZooKeeper:是一个分布式应用程序协调服务器,用于维护Hadoop集群的配置信息、命名信息等,并提供分布式锁同步功能和群组管理功能。 (三)1、MapReduce原理MapReduce计算模式将数据的计算过程分为两个阶段:Map和Reduce。这两个阶段对应了定义的两个处理函数,分别是mapper和reducer。在Map阶段,原始数据被输入mapper进行过滤和转换,获得的中间数据在Reduce阶段作为reducer的输入,经过reducer的聚合处理,获得最终处理结果。2、MapReduce运行框架的组件Client:在此节点上运行了MapReduce程序和JobClient,负责提交MapReduce作业和为用户显示处理结果。JobTracker:负责协调MapReduce作业的执行,是MapReduce运行框架中的主控节点。只有一个。Map TaskTracker:负责执行由JobTracker分配的Map任务。可以有多个。Reduce TaskTracker:负责执行由JobTracker分配的Reduce任务。可以有多个。分布式文件存储系统:存储了应用运行所需要的数据文件及其他相关配置文件。作业:是指MapReduce 程序指定的一个完整计算过程。任务:是MapReduce框架中进行并行计算的基本事务单元,一个作业包含多个任务。3、MapReduce作业的运行流程:作业提交、作业初始化、任务分

hadoop提交作业分析

h a d o o p提交作业分析-标准化文件发布号:(9456-EUATWK-MWUB-WUNN-INNUL-DDQTY-KII

Hadoop提交作业流程分析 bin/hadoop jar xxx.jar mainclass args …… 这样的命令,各位玩Hadoop的估计已经调用过NN次了,每次写好一个Project或对Project做修改后,都必须打个Jar包,然后再用上面的命令提交到Hadoop Cluster上去运行,在开发阶段那是极其繁琐的。程序员是“最懒”的,既然麻烦肯定是要想些法子减少无谓的键盘敲击,顺带延长键盘寿命。比如有的人就写了些Shell脚本来自动编译、打包,然后提交到Hadoop。但还是稍显麻烦,目前比较方便的方法就是用Hadoop eclipse plugin,可以浏览管理HDFS,自动创建MR程序的模板文件,最爽的就是直接Run on hadoop了,但版本有点跟不上Hadoop的主版本了,目前的MR模板还是0.19的。还有一款叫Hadoop Studio的软件,看上去貌似是蛮强大,但是没试过,这里不做评论。那么它们是怎么做到不用上面那个命令来提交作业的呢不知道没关系,开源的嘛,不懂得就直接看源码分析,这就是开源软件的最大利处。 我们首先从bin/hadoop这个Shell脚本开始分析,看这个脚本内部到底做了什么,如何来提交Hadoop作业的。 因为是Java程序,这个脚本最终都是要调用Java来运行的,所以这个脚本最重要的就是添加一些前置参数,如CLASSPATH等。所以,我们直接跳到这个脚本的最后一行,看它到底添加了那些参数,然后再逐个分析(本文忽略了脚本中配置环境参数载入、Java查找、cygwin处理等的分析)。 #run it exec "$JAVA"$JAVA_HEAP_MAX $HADOOP_OPTS -classpath "$CLASSPATH"$CLASS "$@" 从上面这行命令我们可以看到这个脚本最终添加了如下几个重要参数:JAVA_HEAP_MAX、HADOOP_OPTS、CLASSPATH、CLASS。下面我们来一个个的分析(本文基于Cloudera Hadoop 0.20.1+152分析)。 首先是JAVA_HEAP_MAX,这个就比较简单了,主要涉及代码如下:JAVA_HEAP_MAX=-Xmx1000m # check envvars which might override default args if [ "$HADOOP_HEAPSIZE" !="" ];then #echo"run with heapsize $HADOOP_HEAPSIZE" JAVA_HEAP_MAX="-Xmx""$HADOOP_HEAPSIZE""m" #echo$JAVA_HEAP_MAX fi

Hadoop大作业

网络大数据课程作业 目录 1 实验环境部署 0 1.1 主机环境 0 1.2虚拟机环境 0 2 方法介绍 0 2.1 文本聚类 0 2.2 主要的聚类方法 (1) 2.3 K-means算法 (2) 2.4 Hadoop实现 (3) 2.5 Spark实现 (6) 3 实验结果统计 (7) 4 对两个平台上实现方法的对比 (7) 5 收获与建议 (8) 附录 (9)

网络大数据课程作业 1 实验环境部署 1.1 主机环境 处理器Intel(R) Core(TM)2 Duo CPU 2.80GHz 内存8.00GB 操作系统WIN7SP1 64bit 1.2虚拟机环境 VMware? Workstation 10.0.2 build-1744117 处理器2Core 内存4GB 操作系统Ubuntu12.04 LTS Desktop 32bit Hadoop与Spark环境在之前的练习中已经搭好。 2 方法介绍 2.1 文本聚类 文本聚类(Text clustering)主要是依据著名的聚类假设:同类的文档相似度较大,而不同类的文档相似度较小。作为一种无监督的机器学习方法,聚类由于不需要训练过程,以及不需要预先对文档手工标注类别,因此具有一定的灵活性和较高的自动化处理能力,已经成为对文本信息进行有效地组织、摘要和导航的重要手段。 文本聚类可以用于生成一篇简明扼要的摘要文档;对搜索引擎返回的结果进行聚类,使用户迅速定位到所需要的信息;对用户感兴趣的文档(如用户浏览器cache中的网页)聚类,从而发现用户的兴趣模式并用于信息过滤和信息主动推

荐等服务;数字图书馆服务;文档集合的自动整理等等。 2.2 主要的聚类方法 (1)基于划分的方法 基于划分的聚类算法(Partitioning Method)是文本聚类应用中最为普遍的算法。方法将数据集合分成若干个子集,它根据设定的划分数目k选出k个初始聚类中心,得到一个初始划分,然后采用迭代重定位技术,反复在k个簇之间重新计算每个簇的聚类中心,并重新分配每个簇中的对象,以改进划分的质量。使得到的划分满足“簇内相似度高,簇间相似度小”的聚类原则。典型的划分聚类方法有K-means算法和K-medoids算法,两者的区别在于簇代表点的计算方法不同。前者使用所有点的均值来代表簇,后者则采用类中某个数据对象来代表簇。为了对大规模的数据集进行聚类,以及处理复杂形状的聚类,各类改进的划分算法逐渐增多。 基于划分方法的优点是运行速度快,但该方法必须事先确定k的取值。算法容易局部收敛,且不同的初始聚类中心选取对聚类结果影响较大。为此,应用最广泛的k-means算法有很多变种,他们可能在初始k个聚类中心的选择、相似度的计算和计算聚类中心等策略上有所不同,最终实现聚类结果改进的目标。(2)基于层次的方法 基于层次的聚类算法(Hierarchical Method)又叫“分级聚类算法”或“树聚类”,它通过分解给定的数据对象集来创建一个层次。这种聚类方法有两种基本的技术途径:一是先把每个对象看作一个簇,然后逐步对簇进行合并,直到所有对象合为一个簇,或满足一定条件为止;二是把所有对象看成一类,根据一些规则不断选择一个簇进行分解,直到满足一些预定的条件,如类的数目达到了预定值,或两个最近簇的距离达到阈值等。前者称为自下而上的凝聚式聚类,后者称为自上而下的分裂式聚类。 (3)基于密度的方法 绝大多数划分算法都是基于对象之间的距离进行聚类,这类方法只能发现圆形或球状的簇,较难发现任意形状的簇。为此,提出了基于密度的聚类算法(Density-Based Clustering Method),其主要思想是:只要邻近区域的对象或数

Hadoop面试题整理

1 请列出你所知道的hadoop 调度器并简要说明其工作方法 随着MapReduce的流行,其开源实现Hadoop也变得越来越受推崇。在Hadoop系统中,有一个组件非常重要,那就是调度器,它的作用是将系统中空闲的资源按一定策略分配给作业。在Hadoop 中,调度器是一个可插拔的模块,用户可以根据自己的实际应用要求设计调度器。Hadoop中常见的调度器有三种,分别为: (注:本文介绍的Hadoop调度器不够系统化,如果想了解更系统化的Hadoop调度器,可阅读我的最新书籍《Hadoop技术内幕:深入解析MapReduce架构设计与实现原理》(购买说明)第10章“Hadoop多用户作业调度器分析”,分析了当前比较流行的FIFO、Capacity个Fair三种调度器的配置方法、实现机制和优缺点对比,当然,也介绍了其他类型的几种调度器。) (1)默认的调度器FIFO Hadoop中默认的调度器,它先按照作业的优先级高低,再按照到达时间的先后选择被执行的作业。 (2)计算能力调度器Capacity Scheduler 支持多个队列,每个队列可配置一定的资源量,每个队列采用FIFO调度策略,为了防止同一个用户的作业独占队列中的资源,该调度器会对同一用户提交的作业所占资源量进行限定。调度时,首先按以下策略选择一个合适队列:计算每个队列中正在运行的任务数与其应该分得的计算资源之间的比值,选择一个该比值最小的队列;然后按以下策略选择该队列中一个作业:按照作业优先级和提交时间顺序选择,同时考虑用户资源量限制和内存限制。 (3)公平调度器Fair Scheduler 同计算能力调度器类似,支持多队列多用户,每个队列中的资源量可以配置,同一队列中的作业公平共享队列中所有资源,具体算法参见我的博文《Hadoop公平调度器算法解析》 实际上,Hadoop的调度器远不止以上三种,最近,出现了很多针对新型应用的Hadoop调度器。 2 HDFS的存储机制 1. HDFS开创性地设计出一套文件存储方式,即对文件分割后分别存放; 2. HDFS将要存储的大文件进行分割,分割后存放在既定的存储块(Block)中,并通过预先设定的优化处理,模式对存储的数据进行预处理,从而解决了大文件储存与计算的需求; 3. 一个HDFS集群包括两大部分,即NameNode与DataNode。一般来说,一个集群中会有一个NameNode和多个DataNode共同工作; 4. NameNode是集群的主服务器,主要是用于对HDFS中所有的文件及内容数据进行维护,并不断读取记录集群中DataNode主机情况与工作状态,并通过读取与写入镜像日志文件的方式进行存储; 5. DataNode在HDFS集群中担任任务具体执行角色,是集群的工作节点。文件被分成若干个相同大小的数据块,分别存储在若干个DataNode上,DataNode会定期向集群内NameNode发送自己的运行状态与存储内容,并根据NameNode发送的指令进行工作; 6. NameNode负责接受客户端发送过来的信息,然后将文件存储位置信息发送给提交请求的客户端,由客户端直接与DataNode进行联系,从而进行部分文件的运算与操作。 7. Block是HDFS的基本存储单元,默认大小是64M; 8. HDFS还可以对已经存储的Block进行多副本备份,将每个Block至少复制到3个相互独立的硬件上,这样可以快速恢复损坏的数据; 9. 用户可以使用既定的API接口对HDFS中的文件进行操作; 10. 当客户端的读取操作发生错误的时候,客户端会向NameNode报告错误,并请求NameNode排除错误的DataNode后后重新根据距离排序,从而获得一个新的DataNode的读取路径。如果所有的DataNode都报告读取失败,那么整个任务就读取失败; 11. 对于写出操作过程中出现的问题,FSDataOutputStream并不会立即关闭。客户端向NameNode报告错误信息,并直接向提供备份的DataNode中写入数据。备份DataNode被升级为首选DataNode,并在其余2个DataNode中备份复制数据。NameNode对错误的DataNode进行标记以便后续对其进行处理 3 MapReduce 中的两表join 几种方案 1. 概述 在传统数据库(如:MYSQL)中,JOIN操作是非常常见且非常耗时的。而在HADOOP中进行JOIN操作,同样常见且耗时,由于Hadoop的独特设计思想,当进行JOIN操作时,有一些特殊的技巧。 本文首先介绍了Hadoop上通常的JOIN实现方法,然后给出了几种针对不同输入数据集的优化方法。 2. 常见的join方法介绍 假设要进行join的数据分别来自File1和File2. 2.1 reduce side join reduce side join是一种最简单的join方式,其主要思想如下: 在map阶段,map函数同时读取两个文件File1和File2,为了区分两种来源的key/value数据对,对每条数据打一个标签(tag),比如:tag=0表示来自文件File1,tag=2表示来自文件File2。即:map阶段的主要任务是对不同文件中的数据打标签。 在reduce阶段,reduce函数获取key相同的来自File1和File2文件的value list,然后对于同一个key,对File1和File2中的数据进行join(笛卡尔乘积)。即:reduce阶段进行实际的连接操作。REF:hadoop join之reduce side join https://www.360docs.net/doc/8713503111.html,/huashetianzu/article/details/7819244 2.2 map side join 之所以存在reduce side join,是因为在map阶段不能获取所有需要的join字段,即:同一个key对应的字段可能位于不同map中。Reduce side join是非常低效的,因为shuffle阶段要进行大量的数据传输。 Map side join是针对以下场景进行的优化:两个待连接表中,有一个表非常大,而另一个表非常小,以至于小表可以直接存放到内存中。这样,我们可以将小表复制多份,让每个map task内存中存在一份(比如存放到hash table中),然后只扫描大表:对于大表中的每一条记录key/value,在hash table中查找是否有相同的key的记录,如果有,则连接后输出即可。 为了支持文件的复制,Hadoop提供了一个类DistributedCache,使用该类的方法如下: (1)用户使用静态方法DistributedCache.addCacheFile()指定要复制的文件,它的参数是文件的URI(如果是HDFS上的文件,可以这样:hdfs://namenode:9000/home/XXX/file,其中9000是自己配置的NameNode端口号)。JobTracker在作业启动之前会获取这个URI列表,并将相应的文件拷贝到各个TaskTracker的本地磁盘上。(2)用户使用DistributedCache.getLocalCacheFiles()方法获取文件目录,并使用标准的文件读写API读取相应的文件。 REF:hadoop join之map side join https://www.360docs.net/doc/8713503111.html,/huashetianzu/article/details/7821674 2.3 Semi Join Semi Join,也叫半连接,是从分布式数据库中借鉴过来的方法。它的产生动机是:对于reduce side join,跨机器的数据传输量非常大,这成了join操作的一个瓶颈,如果能够在map端过滤掉不会参加join操作的数据,则可以大大节省网络IO。 实现方法很简单:选取一个小表,假设是File1,将其参与join的key抽取出来,保存到文件File3中,File3文件一般很小,可以放到内存中。在map阶段,使用DistributedCache将File3复制到各个TaskTracker上,然后将File2中不在File3中的key对应的记录过滤掉,剩下的reduce阶段的工作与reduce side join相同。 更多关于半连接的介绍,可参考:半连接介绍:https://www.360docs.net/doc/8713503111.html,/view/ae7442db7f1922791688e877.html REF:hadoop join之semi join https://www.360docs.net/doc/8713503111.html,/huashetianzu/article/details/7823326 2.4 reduce side join + BloomFilter 在某些情况下,SemiJoin抽取出来的小表的key集合在内存中仍然存放不下,这时候可以使用BloomFiler以节省空间。 BloomFilter最常见的作用是:判断某个元素是否在一个集合里面。它最重要的两个方法是:add() 和contains()。最大的特点是不会存在false negative,即:如果contains()返回false,则该元素一定不在集合中,但会存在一定的false positive,即:如果contains()返回true,则该元素一定可能在集合中。 因而可将小表中的key保存到BloomFilter中,在map阶段过滤大表,可能有一些不在小表中的记录没有过滤掉(但是在小表中的记录一定不会过滤掉),这没关系,只不过增加了少量的网络IO而已。 更多关于BloomFilter的介绍,可参考:https://www.360docs.net/doc/8713503111.html,/jiaomeng/article/details/1495500 3. 二次排序 在Hadoop中,默认情况下是按照key进行排序,如果要按照value进行排序怎么办?即:对于同一个key,reduce函数接收到的value list是按照value排序的。这种应用需求在join操作中很常见,比如,希望相同的key中,小表对应的value排在前面。 有两种方法进行二次排序,分别为:buffer and in memory sort和value-to-key conversion。 对于buffer and in memory sort,主要思想是:在reduce()函数中,将某个key对应的所有value保存下来,然后进行排序。这种方法最大的缺点是:可能会造成out of memory。 对于value-to-key conversion,主要思想是:将key和部分value拼接成一个组合key(实现WritableComparable接口或者调用setSortComparatorClass函数),这样reduce获取的结果便是先按key 排序,后按value排序的结果,需要注意的是,用户需要自己实现Paritioner,以便只按照key进行数据划分。Hadoop显式的支持二次排序,在Configuration类中有个setGroupingComparatorClass()方法,可用于设置排序group的key值,具体参考:https://www.360docs.net/doc/8713503111.html,/xuxm2007/archive/2011/09/03/2165805.html 4. 后记 最近一直在找工作,由于简历上写了熟悉Hadoop,所以几乎每个面试官都会问一些Hadoop相关的东西,而Hadoop上Join的实现就成了一道必问的问题,而极个别公司还会涉及到DistributedCache原理以及怎样利用DistributedCache进行Join操作。为了更好地应对这些面试官,特整理此文章。 4 介绍一下hbase 过滤器 一、过滤器(Filter) 基础API中的查询操作在面对大量数据的时候是非常苍白的,这里Hbase提供了高级的查询方法:Filter。Filter可以根据簇、列、版本等更多的条件来对数据进行过滤,基于Hbase本身提供的三维有序(主键有序、列有序、版本有序),这些Filter可以高效的完成查询过滤的任务。带有Filter条件的RPC查询请求会把Filter分发到各个RegionServer,是一个服务器端(Server-side)的过滤器,这样也可以降低网络传输的压力。 要完成一个过滤的操作,至少需要两个参数。一个是抽象的操作符,Hbase提供了枚举类型的变量来表示这些抽象的操作符:LESS/LESS_OR_EQUAL/EQUAL/NOT_EUQAL等;另外一个就是具体的比较器(Comparator),代表具体的比较逻辑,如果可以提高字节级的比较、字符串级的比较等。有了这两个参数,我们就可以清晰的定义筛选的条件,过滤数据。 Java代码收藏代码 CompareFilter(CompareOp compareOp,WritableByteArrayComparable valueComparator)

相关主题
相关文档
最新文档