Hadoop MapReduce实战手册

978-7-115-38437-9
作者: 【美】Srinath Perera Thilina Gunarathne
译者: 杨卓荦
编辑: 杨海玲
分类: Hadoop

图书目录:

详情

这是一本简单的一站式指南,书中包含丰富的示例和多样的实际应用场景,以一种简单而直接的方式呈现了90个实战攻略,并给出一步步的指导。本书从获取Hadoop并在集群中运行讲起,依次介绍了高级HDFS,高级Hadoop MapReduce管理,开发复杂的Hadoop MapReduce应用程序,Hadoop的生态系统,统计分析,搜索与索引,聚类、推荐和寻找关联,海量文本数据处理,云部署等内容。

图书摘要

Hadoop MapReduce实战手册
[斯里兰卡]Srinath Perera Thilina Gunarathne 著

杨卓荦 译

杨博淋 审校

人民邮电出版社

北京

图书在版编目(CIP)数据

Hadoop MapReduce实战手册/(斯里)佩雷拉(Perera,S),(斯里)冈纳拉森(Gunarathne,T.)著;杨卓荦译.--北京:人民邮电出版社,2015.3

书名原文:Hadoop MapReduce cookbook

ISBN 978-7-115-38437-9

Ⅰ.①H… Ⅱ.①佩…②冈…③杨… Ⅲ.①数据处理软件—手册②软件工具—程序设计—手册 Ⅳ.①TP274-62②TP311.56-62

中国版本图书馆CIP数据核字(2015)第032695号

版权声明

Copyright ©2013 Packt Publishing. First published in the English language under the title Hadoop MapReduce Cookbook.

All Rights Reserved.

本书由英国Packt Publishing 公司授权人民邮电出版社出版。未经出版者书面许可,对本书的任何部分不得以任何方式或任何手段复制和传播。

版权所有,侵权必究。

◆著 [斯里兰卡]Srinath Perera Thilina Gunarathne

译 杨卓荦

审校 杨博淋

责任编辑 杨海玲

责任印制 张佳莹 焦志炜

◆人民邮电出版社出版发行  北京市丰台区成寿寺路11号

邮编 100164  电子邮件 315@ptpress.com.cn

网址 http://www.ptpress.com.cn

三河市海波印务有限公司印刷

◆开本:800×1000 1/16

印张:15.75

字数:306千字  2015年3月第1版

印数:1-3000册  2015年3月河北第1次印刷

著作权合同登记号 图字:01-2013-4469号

定价:49.00元

者服务热线:(010)81055410 印装质量热线:(010)81055316

反盗版热线:(010)81055315

内容提要

这是一本学习Hadoop MapReduce 的一站式指南,完整介绍了Hadoop生态体系,包括Hadoop平台安装、部署、运维等,以及Hadoop生态系统成员Hive、Pig、HBase、Mahout等。最重要的是,书中包含丰富的示例和多样的实际应用场景,以一种简单而直接的方式呈现了90个实战攻略,并给出一步步的指导。本书从获取Hadoop并在集群中运行Hadoop讲起,依次介绍了高级HDFS,高级Hadoop MapReduce管理,开发复杂的Hadoop MapReduce应用程序,Hadoop的生态系统,统计分析,搜索与索引,聚类、推荐和寻找关联,海量文本数据处理,云部署等内容。

本书是为各个层次的Hadoop开发人员准备的,是对Hadoop没有了解而想快速上手并应用Hadoop技术的读者的一站式学习手册,也是有一定Hadoop使用经验的读者解决实际问题的实用参考手册。

前言

本书目标是帮助读者学会处理大型的复杂数据集。本书虽从简单的例子开始,但仍然可以看到深入的内容。这是一本简单的一站式指南,传授如何完成复杂的事情。它以一种简单而直接的方式呈现了90个攻略,给出了一步步的指导和真实环境的应用示例。

本产品包括在Apache软件基金会(http://www.apache.org/)开发的软件。

本书涵盖的内容

第1章解释了如何以单点模式以及集群模式安装和运行Hadoop。

第2章介绍了一套高级的HDFS操作,在处理大规模数据时,无论是用Hadoop MapReduce还是用非MapReduce用例,这些操作都很有用。

第3章解释了如何改变Hadoop部署的配置和安全性,以及如何调试。

第4 章介绍了几种高级的Hadoop MapReduce 特性,这些特性将有助于你开发高度定制化的、高效的MapReduce应用程序。

第5章介绍了其他与Hadoop相关的项目,如HBase、Hive和Pig。

第6章解释了如何使用Hadoop来计算基本的统计分析信息。

第7章介绍几种可以与Apache Hadoop协同使用的工具和技术,让你可以进行大规模的搜索和索引。

第8章介绍了如果使用Hadoop实现复杂的算法,如聚类、推荐和关系发现。

第9章解释了如何使用Hadoop和Mahout处理海量文本数据集,以及如何使用Hadoop实现数据预处理和加载操作。

第10章解释了如何使用亚马逊弹性MapReduce(Elastic MapReduce,EMR)和Apache Whirr在云基础设施上部署和执行Hadoop MapReduce、Pig、Hive和HBase 计算。

阅读本书需要做的准备

你需要准备一台运行 Linux 操作系统的计算机,并且能够连接互联网。另外,需要具备必要的Java知识。

本书的目标读者

本书是为大数据的爱好者以及准 Hadoop 程序员准备的,也适用于那些从未使用过Hadoop的Java程序员,或者已经了解了Hadoop和MapReduce但想要尝试新事物并深入细节的Java程序员。本书也是大多数Hadoop任务的一站式参考手册。

书中的排版约定

你会发现,本书中使用了一些不同样式的文本,用以区别不同类型的信息。下面是这些样式的示例及对其含义的解释。

正文中的代码字体是这样的:“从现在的情况来看,我们应该把解压后的Hadoop目录叫做HADOOP_HOME。”

代码块设置如下:

public void map(Object key, Text value, Context context)

throws IOException, InterruptedException

{

StringTokenizer itr = new StringTokenizer(value.toString());

while (itr.hasMoreTokens())

{

word.set(itr.nextToken());

context.write(word, new IntWritable(1));

}

}

命令行的输入或输出如下所示:

>tar -zxvf hadoop-1.x.x.tar.gz

新的术语重要的词汇会以粗体的形式显示。在屏幕上显示的单词,例如出现在菜单或者对话框中的文本,在正文中显示为:“单击Create Bucket,创建一个S3存储桶,用于上传输入数据。”

这样的方框中出现的是警告或重要的注解。

这样的方框中出现的是技巧和提示。

读者反馈

我们总是欢迎来自读者的反馈。请告诉我们你觉得这本书怎么样——喜欢哪些内容,不喜欢哪些内容。读者的反馈对我们来说很重要,因为通过反馈,我们可以挖掘出更多有益于读者的主题。

普通的反馈只需发送电子邮件到 feedback@packtpub.com,并在邮件主题中注明相应的书名即可。

如果你是某一主题的专家并且对写作或撰写一本书有兴趣,可以访问 www.packtpub.com/authors,阅读我们的作者指南。

客户支持

现在,你已经成为 Packt 出版社的尊贵用户,为了使你的购买物超所值,我们为你做了很多事情。

下载示例代码

你可以通过http://www.PacktPub.com上你的账户,下载到你购买的Packt图书的所有示例代码文件。如果你是从其他地方购买的本书,那么可以在 http://www.PacktPub.com/support注册,我们会把这些文件直接通过电子邮件发送给你。

勘误

尽管我们已尽力确保内容的准确性,但错误仍然在所难免。如果你在书中发现了错误(不管是文字错误还是代码错误),并且愿意反馈给我们,我们将不胜感激。这样做可以让其他人免受这些错误的困扰,并且可以帮我们改进本书的后续版本。如果你发现任何错误,请访问http://www.packtpub.com/support,选择书名,单击Submit Errata(提交勘误)链接,填写详细的勘误信息。一旦提交的勘误被确认,就会被采纳并上传到我们的网站,或者追加到该书已有的勘误列表中。任何已有的勘误都可以从 http://www.packtpub.com/support选择书名进行查看。

版权说明

盗版的盛行是互联网上一直存在的问题。在Packt,我们对待版权及许可的保护非常认真,如果你发现在互联网上有任何非法复制我们作品的情况,无论是什么形式,都请立即将网络地址或网站名称提供给我们,以便我们采取补救措施。

请通过copyright@packtpub.com联系我们,并附上涉嫌盗版内容的链接。

我们非常感谢你对我们作者权益的保护,你的协助同时也保障了我们带给你更多有价值内容的能力。

疑问

如果你对本书的某个方面有任何问题,可以通过questions@packtpub.com联系我们,我们会尽力解决。

作者介绍

Srinath Perera是WSO2公司的高级软件架构师,与CTO一同全观整个WSO2平台架构。同时,他也是斯里兰卡软件基金会的一位研究科学家,并作为访问学者在莫勒图沃大学计算机科学与工程系授课。他是 Apache Axis2 开源软件项目的联合创始人,他自 2002年以来一直参与Apache Web Service 项目,并且是Apache软件基金会和Apache Web 服务项目PMC的成员。Srinath 也是Apache Axis、Axis2 和Geronimo 开源项目的committer。

他在美国印第安纳大学伯明顿分校获得博士和硕士学位,在斯里兰卡莫勒图沃大学获得了计算科学与工程学士学位。

Srinath已经撰写了许多技术文章和同行评审的研究文章,可以从他的个人网站找到更多细节。他还经常在技术会议上做演讲。

他长期研究大规模分布式系统。他的日常工作与大数据技术(如Hadoop和Cassandra)结合很紧密。他还在莫勒图沃大学研究生班教授并行计算,主要是基于Hadoop。

我要感谢我的妻子Miyuru和我的父母,他们的支持让我不断前进。我也要感谢 WSO2 的Sanjiva 鼓励我们在工作之外为这些项目尽自己一份力。最后,我要感谢我WSO2的同事,他们的创意与陪伴在很多方面促成了这本书。

Thilina Gunarathne 是印第安纳大学信息与计算学院博士。他在使用Apache Hadoop以及大规模数据密集型计算技术方面有着丰富的经验。他目前的主要工作是致力于研发在云环境执行可扩展的、高效的大规模数据密集型计算的技术。

Thilina发表了很多论文,并且同行评审了很多分布式计算和并行计算领域的研究论文,包括一些在云环境扩展MapReduce模型进行有效的数据挖掘和数据分析的论文。Thilina经常在学术界和工业界会议上发表演讲。

Thilina 自 2005 年以来,在 Apache 软件基金会下贡献了若干个开源项目,并成为committer和PMC成员。在开始研究生学习之前,Thilina在WSO2公司担任高级软件工程师,专注于开源中间件开发。Thilina 2006年在斯里兰卡莫勒图沃大学获得计算机科学与工程学士学位,2009年在美国印第安纳大学伯明顿分校获得计算机科学硕士学位,2013年获得分布式和并行计算领域博士学位。

没有众多需要感谢的人的间接和直接的帮助,这本书也不会成功。感谢我的妻子和儿子,容忍我错过家人团聚的时光,感谢他们在我写作期间给予我的爱与鼓励。感谢我的父母,没有他们的爱、指引和鼓励,将不会有现在的我。

感谢我的导师Geoffrey Fox 教授,感谢他出色的指导,并为我提供环境来使用Hadoop和相关技术。感谢HBase、Mahout、Pig、Hive、Nutch、Lucene社区开发出了如此伟大的开源产品。感谢Apache软件基金会培育出如此充满活力的开源社区。

感谢 Packt 的编辑为我提供写这本书的机会,并全程提供反馈和指导。感谢审稿人员评审这本书,指出我的错误,并提出许多有用的建议。

感谢我过去和现在的所有导师和老师,包括 WSO2 公司的 Sanjiva Weerawarana博士、Dennis Gannon教授、Judy Qiu 教授、Beth Plale教授,感谢我印第安纳大学和莫勒图沃大学的所有教授,感谢他们给我所有的知识和指导。感谢我过去和现在的所有同事,感谢他们与我进行许多深刻的讨论和知识分享。

审稿人介绍

岩崎正毅(Masatake Iwasaki)是NTT DATA公司的软件工程师。他提供开源软件技术咨询,如Hadoop、HBase和PostgreSQL。

山下新一(Shinichi Yamashita)是日本NTT DATA 公司OSS专业服务部总工程师。他在软件和中间件(Apache、Tomcat、PostgreSQL和Hadoop生态系统)有7年多的工程经验。NTT DATA 在世界各地的任何地方都是你的创新合作伙伴。它提供专业的服务,从咨询和系统开发业务到IT外包。在日本,他出版过一些Hadoop方面的书籍。

我感谢我的同事们。

第1章 搭建Hadoop并在集群中运行

本章将学习以下内容:

□ 在你的机器上安装Hadoop

□ 写WordCountMapReduce示例程序,打包并使用独立的Hadoop运行它

□ 给WordCountMapReduce程序增加combiner步骤

□ 安装HDFS

□ 使用HDFS监控UI

□ HDFS的基本命令行文件操作

□ 在分布式集群环境中设置Hadoop

□ 在分布式集群环境中运行WordCount程序

□ 使用MapReduce监控UI

1.1 简介

很多年来,想要存储和分析数据的用户都需要先将数据存储在数据库中,然后再通过SQL查询来处理。万维网已经改变了这个时代的大多数假设。万维网上的数据是非结构化的大型数据,以至于数据库既不能以某种模式捕捉它们,也无法扩展存储和处理它们。

Google是最早面对这类问题的组织之一,他们想要下载镜像因特网数据并索引它们以支持搜索查询。他们创建了一个用于大规模数据处理的框架,借鉴了函数式编程范式的“map”函数和“reduce”函数。它们被称为MapReduce范式。

Hadoop 最广为人知,同时也是最最广泛使用的 MapReduce 范式实现。本章将介绍Hadoop,描述如何安装Hadoop,并演示如何使用Hadoop运行你的第一个MapReduce作业。

Hadoop 的安装由 4 种类型的节点构成:NameNode、DataNode、JobTracker 和TaskTracker。HDFS节点(NameNode和DataNode)提供了一套分布式文件系统,在这套系统上,JobTracker管理作业,每个TaskTracker各自运行该作业的一部分任务。用户提交MapReduce作业给JobTracker,JobTracker运行这些初始作业的Map和Reduce部分,收集中间结果,并最终输出结果。

Hadoop提供了以下三种可供选择的安装方式。

□ 本地模式:这是一种解压缩即运行的模式,能让你马上开始,Hadoop的各个部分都运行在同一JVM中。

□ 伪分布式模式:这种模式将使用不用的 java 虚拟机运行 Hadoop 的不同部分,但这些java虚拟机运行在一台机器上。

□ 分布式模式:这才是真正的跨多台机器的安装模式。

我们将在前三节中讨论本地模式,在后三节中讨论伪分布式和分布式模式。

1.2 在你的机器上安装Hadoop

本节讲述如何在本地模式下运行Hadoop。

准备工作

从 http://www.oracle.com/technetwork/java/javase/downloads/index.html下载并安装Java 1.6或者更高版本。

操作步骤

现在让我们来完成Hadoop的安装。

1. 从http://hadoop.apache.org/下载最新的Hadoop 1.0分支发行版。

2. 使用下列命令解压Hadoop发行版。必须将文件名中的x.x换成你实际下载的版本号。如果你使用的是Windows,可以使用自己喜欢的解压缩工具(如WinZip或者WinRAR)去解压发行包。从现在的情况来看,我们应该把解压后的Hadoop目录叫做HADOOP_HOME。

>tar -zxvf hadoop-1.x.x.tar.gz

3. 在解压完发行版之后,就可以使用 Hadoop 的本地模式了。安装也就完成了。现在,你可以通过bin/hadoop命令运行Hadoop作业了,我们将在下一节中详尽阐述。

工作原理

Hadoop本地模式并不启动任何服务进程,而是在同一个JVM中完成所有的工作。当你在Hadoop本地模式中提交一个作业时,这个作业启动一个JVM去运行并完成该作业。作业的输出和行为与分布式的Hadoop作业相同,只是作业只能使用当前的节点运行任务。在1.3节中,我们将探索如何使用解压后的Hadoop发行版去运行一个MapReduce程序。

下载示例代码

你可以在 http://www.packtpub.com 上使用自己的账户下载你购买的所有 Packt 图书的示例代码文件。如果你是从其他地方购买的此书,那么你可以访问http://www.packtpub.com/support进行注册,这些文件会直接发送到你的电子邮箱里。

1.3 写WordCountMapReduce示例程序,打包并使用独立的Hadoop运行它

本节传授如何写一个简单的MapReduce程序,以及如何执行它,如图1-1所示。

要运行MapReduce作业,用户需要提供一个map函数、一个reduce函数、输入数据,以及输出数据的位置。在执行时,Hadoop实际执行如下步骤。

1. Hadoop 通过换行符将输入数据分解成多个数据项,并且在每一个数据项上运行一次map函数,将这个数据项作为对应map函数的输入。执行完成时,每个map函数输出一个或者多个键值对。

2. Hadoop收集所有map函数产生的键值对,并且通过键对它们进行排序,将具有相同值的键值对分成一组。

3. 对于每一个不同的键,Hadoop会运行一次 reduce函数,该函数的输入是这个键和它所对应的值的列表。

4. reduce函数会输出一个或多个键值对,然后Hadoop将它们作为最终结果写入文件。

准备工作

从本书所对应的源代码中,选择第1章所对应的源代码,即 chapter1_src.zip。然后,使用你喜欢的 Java 集成开发环境(IDE),例如 Eclipse,导入源代码。你需要将HADOOP_HOME中名为 hadoop-core的 JAR 文件和 HADOOP_HOME/lib目录下的所有其他JAR文件都添加到IDE的类路径(classpath)下。

从http://ant.apache.org/下载并安装ApacheAnt。

操作步骤

现在来写我们的第一个Hadoop MapReduce程序。

1. WordCount示例的输入是一组文档,使用MapReduce来对文档集合中的每个单词进行计数。可以从src/chapter1/Wordcount.java找到示例代码。这段代码有三部分:mapper、reducer和主程序。

2. mapper 实现 org.apache.hadoop.mapreduce.Mapper接口。Hadoop 运行时,接收输入文件中的每一行作为 mapper 的输入。map函数使用空白字符作为分隔符,将每一行分解成为多个子串,并且为每个子串(单词)输出一个(word, 1)键值对作为函数输出。

public void map(Object key, Text value, Context context

)throws IOException, InterruptedException

{

StringTokenizeritr = new StringTokenizer(value.toString());

while (itr.hasMoreTokens())

{

word.set(itr.nextToken());

context.write(word, new IntWritable(1));

}

}

3. reduce函数接收所有具有相同键的值作为输入,将该键和该键出现的次数作为输出。

public void reduce(Text key, Iterable<IntWritable> values,

Context context

) throws IOException, InterruptedException

{

int sum = 0;

for (IntWritableval : values)

{

sum+=val.get();

}

result.set(sum);

context.write(key, result);

}

4. main程序将配置放在一起,并将作业提交给Hadoop运行。

Configuration conf = new Configuration();

String[] otherArgs = new GenericOptionsParser(conf, args).

getRemainingArgs();

if (otherArgs.length != 2) {

System.err.println("Usage: wordcount<in><out>");

System.exit(2);

}

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

job.setJarByClass(WordCount.class);

job.setMapperClass(TokenizerMapper.class);

//Uncomment this to

//job.setCombinerClass(IntSumReducer.class);

job.setReducerClass(IntSumReducer.class);

job.setOutputKeyClass(Text.class);

job.setOutputValueClass(IntWritable.class);

FileInputFormat.addInputPath(job, new Path(otherArgs[0]));

FileOutputFormat.setOutputPath(job, new Path(otherArgs[1]));

System.exit(job.waitForCompletion(true) ? 0 : 1);

5. 你可以通过下列命令从示例代码的根目录编译示例程序,该命令使用ApacheAnt:

>ant build

如果还没有准备好 Apache Ant,那么应该按照 http://ant.apache.org/manual/install.html上给出的说明安装ApacheAnt。或者,也可以使用包含源代码的编译好的JAR文件。

6. 将目录跳转到 HADOOP_HOME,并且将 hadoop-cookbookchapter1.jar 文件复制到HADOOP_HOME目录。在HADOOP_HOME下创建一个名为input的目录,并将README.txt文件复制到这个目录下。或者,也可以将任意的文本文件复制到这个input目录。

7. 使用下列命令运行示例程序。在这里,chapter1.WordCount是我们需要运行的main类的名称。在运行该命令时,会在终端看到下面的输出:

>bin/hadoop jar hadoop-cookbook-chapter1.jar chapter1.WordCount input output

12/04/11 08:12:44 INFO input.FileInputFormat: Total input paths to process : 16

12/04/11 08:12:45 INFO mapred.JobClient: Running job: job_local_0001

12/04/11 08:12:45 INFO mapred.Task: Task:attempt_local_0001_m_000000_0

is done. And is in the process of commiting

...

...

12/04/11 08:13:37 INFO mapred.JobClient: Job complete: job_local_0001

...

8. 在输出目录中有一个文件名类似于 part-r-XXXXX 的文件,该文件用于存放文档中每一个单词的计数。恭喜!你已经成功地运行了自己的第一个MapReduce程序。

工作原理

在前面的示例中,MapReduce在本地模式下工作,没有启动任何服务进程,而是使用本地文件系统作为输入、输出和工作数据的存储系统。图1-2显示了WordCount程序幕后发生的事。

工作流如下。

1. Hadoop读取输入,以换行符为分隔符将其拆成行,然后以每行作为参数运行map函数。

2. map函数对行进行标记化处理,为每个标记(单词)输出一个键值对(word,1)。

3. Hadoop收集所有的(word,1)对,按word对其进行排序,按每个不同的键对输出的值进行分组,以键及该键的所有值为参数对每个不同的键调用一次reduce。

4. reduce函数使用这些值对每个单词出现的次数进行计数,并将结果以键值对的形式输出。

5. Hadoop将最终的输出结果写到输出目录中。

更多参考

作为一个可选步骤,可以将 input 目录复制到你为示例程序创建的基于 IDE 的项目(Eclipse 项目)的顶层。现在可以以 input output作为参数直接从IDE 运行 WordCount类。这将像以前运行普通程序一样运行示例。这种从IDE中运行MapReduce作业的方式,是非常有用的调试MapReduce作业的方式。

这个示例不只可用本地计算机上安装的Hadoop运行,还可以在带有HDFS分布式文件系统的分布式Hadoop集群上运行。1.5节和1.8节将讨论如何在分布式安装中运行此示例。

1.4 给WordCount MapReduce程序增加combiner步骤

运行 map函数后,如果有许多键值对使用相同的键,那么Hadoop必须将所有这些值传送到 reduce函数。这可能会产生一个非常显著的开销。为了优化这样的场景,Hadoop支持一个专门的函数——combiner。如果配置了 combiner,Hadoop 会在运行完成 mapper之后、调用reducer之前,在map节点所在的那个节点调用combiner。这可以显著地减少传输到reduce步骤的数据量。

本节将说明如何在1.3节介绍的WordCount示例程序中使用combiner。

操作步骤

现在,让我们加入combiner配置来运行MapReduce作业。

1. combiner 必须和 reduce 函数具有相同的接口。对于 WordCount 示例程序,我们将会复用reduce函数作为combiner。

2. 为了让MapReduce作业使用combiner,需要在示例程序中取消//job.setCombinerClass.(IntSumReducer.class);这行的注释,然后重新编译代码。

3. 将 hadoop-cookbook-chapter1.jar文件复制到 HADOOP_HOME目录,并且用前一节介绍的方式运行WordCount。确保运行作业之前删除了旧的输出目录。

4. 最终结果会放在output目录下。

工作原理

要激活combiner,用户应该提供mapper、reducer和combiner作为MapReduce作业的输入。在该环境中,一旦mapper函数执行完成,Hadoop就在mapper函数所在的节点上执行combiner。使用这种方法,combiner可以预先处理mapper所产生的数据,然后再将结果发送给reducer,从而减少转移的数据量。

例如,WordCount 示例,combiner 从map 步骤接收多个(word, 1)对作为输入,并输出一个(word, N)对。例如,如果输入文档中单词“the”出现了 10 000 次,那么 mapper将产生10 000个(the, 1)对,而combiner将只产生一个(the, 10,000),从而减少传输给reduce任务的数据量。

然而,combiner只适用于满足代数交换律和结合律的函数。例如,同样的思路对计算平均值就会无效。由于平均值是不满足交换律和结合律的,在这种情况下,combiner 将会得到一个错误的结果。

更多参考

虽然在示例程序中,我们是复用reduce函数实现的combiner功能,你也可以写自己的combiner函数,就像我们在前一节中介绍的map和reduce函数。然而,combiner函数的签名必须与reduce函数的签名完全一致。

在本地配置Hadoop的情况下,使用combiner不会产生显著的收益。然而,如1.8节所述,在分布式的集群环境中,combiner可以提供显著的收益。

1.5 安装HDFS

HDFS是Hadoop的分布式文件系统。MapReduce任务使用HDFS读取和写入数据。HDFS部署包括一个NameNode和多个DataNode,如图1-3所示。

要想安装 HDFS,需要先配置 NameNode 和 DataNode,然后在 slave 文件中指定DataNode列表。当我们启动NameNode时,启动脚本将自动启动这些DataNode列表。

准备工作

无论使用的是单台机器还是多台机器,本节都适用。如果你用的是多台机器,则应该选择一台机器作为主节点来运行HDFS NameNode。如果你使用的是单台机器,则可以用它既作NameNode,又作DataNode。

1. 在用于安装HDFS集群的所有机器上安装Java。

2. 如果你使用的是Windows机器,则需要在每一台机器上都安装Cygwin和SSH 服务。链接http://pigtail.net/LRP/printsrv/cygwin-sshd.html提供了详细安装说明。

操作步骤

现在让我们在分布式模式下安装HDFS。

1. 从主节点到从节点依次启用SSH服务。通过运行以下命令之一检查确认,可以跳过输入密码直接使用SSH服务登录到本地机器或其他所有节点机器:

□ >sshlocalhost

□ >sshIPaddress

2. 如果上述命令返回错误或要求输入密码,那么可以执行下列命令来创建SSH密钥:

>ssh-keygen -t dsa -P '' -f ~/.ssh/id_dsa

将~/.ssh/id_dsa.pub文件复制到集群中的所有节点。然后通过运行以下命令(如果authorized_keys文件不存在,则运行以下命令。否则,跳到cat命令),将SSH密钥写入每个节点的~/.ssh/authorized_keys文件:

>touch ~/.ssh/authorized_keys&&chmod 600 ~/.ssh/authorized_keys

现在配置权限设置,将你的密钥写入~/.ssh/authorized_keys文件。

>cat ~/.ssh/id_dsa.pub >> ~/.ssh/authorized_keys

然后你就可以使用下面的命令登录了:

>sshlocalhost

这个命令在主目录的.ssh/目录创建一个SSH密钥对,并且将生成的带SSH的公钥注册为一个信任密钥。

3. 在每台机器上创建一个目录,用于存储HDFS数据。我们称那个目录为HADOOP_DATA_DIR。

现在,让我们创建两个子目录——HADOOP_DATA_DIR/data 和 HADOOP_DATA_DIR/name。

通过为每个目录运行以下命令,将目录权限更改为755:

>chmod 755 <name of dir>

4. 在NameNode上,将目录跳转到解压后的HADOOP_HOME目录。然后将所有从节点的IP地址写入 HADOOP_HOME/conf/slaves 文件,每行一个独立的 IP 地址。当我们启动NameNode时,它会使用slaves文件启动DataNode。

5. 在所有机器上,编辑HADOOP_HOME/conf/hadoop-env.sh,取消该文件中JAVA_HOME行的注释,将其指向本地的Java安装目录。例如,如果Java安装在/opt/jdk1.6下,那么可以将JAVA_HOME行改为export JAVA_HOME=/opt/jdk1.6。

6. 在每个节点的HADOOP_HOME/conf目录下,将下面的配置代码添加到core-site.xml文件和 hdfs-site.xml文件中。在添加配置之前,把 MASTER_NODE字符串替换为主节点的IP地址,并把HADOOP_DATA_DIR替换为第一步创建的目录。

HADOOP_HOME/conf/core-site.xml

<configuration>

<property>

<name>fs.default.name</name>

<!-- URL of MasterNode/NameNode -->

<value>hdfs://MASTER_NODE:9000/</value>

</property>

</configuration>

HADOOP_HOME/conf/hdfs-site.xml

<configuration>

<property>

<name>dfs.name.dir</name>

<!-- Path to store namespace and transaction logs -->

<value>HADOOP_DATA_DIR/name</value>

</property>

<property>

<name>dfs.data.dir</name>

<!-- Path to store data blocks in datanode -->

<value>HADOOP_DATA_DIR/data</value>

</property>

</configuration>

7. 从NameNode上,运行以下命令来格式化一个新的文件系统:

>bin/hadoopnamenode –format

12/04/09 08:44:50 INFO namenode.NameNode: STARTUP_MSG:

/************************************************************

...

12/04/09 08:44:51 INFO common.Storage: Storage directory /Users/srinath/playground/hadoop-book/hadoop-temp/dfs/name has been successfully formatted.

12/04/09 08:44:51 INFO namenode.NameNode: SHUTDOWN_MSG:

/************************************************************

SHUTDOWN_MSG: Shutting down NameNode at Srinath-s-MacBook-Pro.

local/172.16.91.1

************************************************************/

8. 使用下面的命令开始HDFS的安装:

>bin/start-dfs.sh

这个命令将首先启动一个NameNode进程。然后,它会查看HADOOP_HOME/conf/slaves文件,启动DataNode进程。控制台将打印类似下面的消息。

startingnamenode, logging to /root/hadoop-setup-srinath/hadoop-1.0.0/libexec/../logs/hadoop-root-namenode-node7.beta.out

209.126.198.72: starting datanode, logging to /root/hadoop-setupsrinath/hadoop-1.0.0/libexec/../logs/hadoop-root-datanode-node7.beta.out

209.126.198.71: starting datanode, logging to /root/hadoop-setupsrinath/hadoop-1.0.0/libexec/../logs/hadoop-root-datanode-node6.beta.out

209.126.198.72: starting secondarynamenode, logging to /root/hadoop-setup-srinath/hadoop-1.0.0/libexec/../logs/hadoop-rootsecondarynamenode-node7.beta.out

Hadoop使用集中式架构来管理元数据。在这种设计中,NameNode持有所有文件的信息,记录文件与数据库的对应关系及数据块的具体位置。NameNode是单点,当它发生故障时,它将停止HDFS集群的所有操作。为了避免这种情况,Hadoop支持secondary NameNode ,该进程备份了NameNode中的所有数据。如果NameNode发生故障,secondary NameNode会取代其位置 [1]

9. 访问链接http://MASTER_NODE:50070/,看是否能看到HDFS 启动页面。在这里,请将MASTER_NODE替换为运行HDFS NameNode的主节点的IP 地址。

10. 最后,使用下面的命令关闭HDFS集群:

>bin/stop-dfs.sh

工作原理

NameNode 启动时,将读取 HADOOP_HOME/conf/slaves 文件,找到需要启动的DataNode列表,启动它们,并设置HDFS集群。在1.7节中,我们将探讨如何使用HDFS来存储和管理文件。

HDFS安装只是整个Hadoop安装的一部分。1.8节中会介绍如何设置Hadoop的其余部分。

1.6 使用HDFS监控UI

HDFS包含一个监控Web控制台,用于验证安装和监控HDFS集群。它也可以让用户浏览HDFS文件系统的内容。在本节中,我们将探讨如何访问HDFS监控UI,并验证安装。

准备工作

根据前一节所描述的内容,启动HDFS集群。

操作步骤

让我们从访问HDFS的Web控制台开始。

1. 使用浏览器访问链接http://MASTER_NODE:50070/,看是否能看到HDFS 启动页面。在这里,请将MASTER_NODE替换为运行HDFS NameNode的主节点的IP地址。

2. 图 1-4 所示的截图显示了当前安装的 HDFS 的状态,包括节点的数量、总存储量、各节点所占存储。它也允许用户通过网页浏览HDFS文件系统。

1.7 HDFS的基本命令行文件操作

HDFS是一个分布式的文件系统,就像一个Unix文件系统一样,它允许用户使用shell命令操纵文件系统。本节将说明如何使用HDFS的基本命令行来执行这些操作。

值得注意的是,每一条HDFS命令都有一个与之一一对应的Unix命令。例如,下面的命令:

>hadoopdfs –cat /data/foo.txt

该命令用于读取/data/foo.txt文件,并把它打印到屏幕上,就像Unix 系统的 cat命令一样。

准备工作

通过以下安装HDFS的攻略,启动HDFS服务器。

操作步骤

1. 将工作目录跳转到HADOOP_HOME。

2. 运行下面的命令来新建一个名为/test的目录:

>bin/hadoopdfs -mkdir /test

3. HDFS 文件系统的根目录为/,就像 Unix 文件系统的根目录一样。运行以下命令可以列出HDFS根目录的内容:

>bin/hadoopdfs -ls /

4. 运行下面的命令将本地readme文件复制到/test目录下:

>bin/hadoopdfs -put README.txt /test

5. 运行下面的命令列出/test目录的内容:

>bin/hadoopdfs -ls /test

Found 1 items

-rw-r--r-- 1 srinathsupergroup 1366 2012-04-10 07:06 /test/README.txt

6. 运行以下命令将/test/README.txt文件复制到本地目录:

>bin/hadoopdfs -get /test/README.txt README-NEW.txt

工作原理

当命令发出后,客户端将代表用户与HDFS NameNode通信,并执行相关操作。通常,我们使用以/开头的路径来引用文件或文件夹,如/data,客户端将根据 HADOOP_HOME/conf目录中的配置项来选择NameNode。

然而,如果需要的话,我们可以使用一个完全限定路径来强制客户端跟一个特定的NameNode 进行通信。例如,hdfs://bar.foo.com:9000/data,会要求客户端与运行在bar.foo.com主机9000端口上的NameNode进行通信。

更多参考

HDFS支持大多数的Unix命令,如cp、mv和chown,它们与上面讨论的命令一样,遵循相同的模式。文档http://hadoop.apache.org/docs/r1.0.3/file_system_shell.html提供了所有支持命令的列表。我们将在本书中通篇使用这些命令。

1.8 在分布式集群环境中设置Hadoop

Hadoop的部署包括一套HDFS、一个JobTracker和多个TaskTracker。在1.5节中,我们讨论了HDFS的部署。为了设置Hadoop,我们需要配置JobTracker和TaskTracker,然后在HADOOP_HOME/conf/slaves文件中指定TaskTracker列表。当我们启动JobTracker时,它会启动相应的TaskTracker节点列表。图1-5描述了一套完整的Hadoop部署。

准备工作

无论使用的是单台机器还是多台机器,本节都适用。如果你用的是多台机器,则应该选择一台机器作为主节点,用于运行HDFS NameNode 和JobTracker 进程。如果你使用的是单台机器,则可以用它既作主节点,又作从节点。

1. 在所有用于安装Hadoop集群的机器上安装Java。

2. 如果你使用的是Windows机器,则需要先在每一台机器上都安装Cygwin和SSH服务。链接http://pigtail.net/LRP/printsrv/cygwin-sshd.html提供了详细的说明。

操作步骤

让我们通过设置JobTracker和TaskTracker来设置Hadoop。

1. 在每一台机器上,创建一个目录,用于存放 Hadoop 数据。我们把这个目录称作HADOOP_DATA_DIR。然后创建三个子目录,HADOOP_DATA_DIR/data、HADOOP_DATA_DIR/local和HADOOP_DATA_DIR/name。

2. 在所有机器上设置 SSH 密钥,这样我们就可以从主节点登录到所有的节点。1.5 节详细介绍了SSH设置。

3. 使用>tar zxvf hadoop-1.x.x.tar.gz 命令把 Hadoop 发行包解压缩到所有机器的相同位置。你可以使用任何Hadoop的1.0分支发行包。

4. 在所有机器上,编辑 HADOOP_HOME/conf/hadoop-env.sh,删除文件中 JAVA_HOME行的注释,并将其指向你的本地Java安装目录。例如,如果Java安装在/opt/jdk1.6下,那么就要将JAVA_HOME行改为export JAVA_HOME=/opt/jdk1.6。

5. 将主节点(运行 JobTracker 和 NameNode 的机器)的 IP 地址作为一行放置在HADOOP_HOME/conf/master中。如果你正在进行单节点部署,则保留当前值,填写为localhost。

209.126.198.72

6. 然后将所有从节点的IP 地址写入HADOOP_HOME/conf/slaves文件,每行一个独立的IP地址。

209.126.198.72

209.126.198.71

7. 在每个节点的 HADOOP_HOME/conf 目录里面,将以下内容添加到 core-site.xml、hdfs-site.xml和mapred-site.xml中。在添加这些配置之前,要先将MASTER_NODE字符串替换为主节点的IP地址,HADOOP_DATA_DIR替换为第一步创建的目录。

将NameNode的URL添加到HADOOP_HOME/conf/core-site.xml中。

<configuration>

<property>

<name>fs.default.name</name>

<value>hdfs://MASTER_NODE:9000/</value>

</property>

</configuration>

在HADOOP_HOME/conf/hdfs-site.xml内添加元数据(名称空间)和本地数据存储的位置 [2]

<configuration>

<property>

<name>dfs.name.dir</name>

<value>HADOOP_DATA_DIR/name</value>

</property>

<property>

<name>dfs.data.dir</name>

<value>HADOOP_DATA_DIR/data</value>

</property>

</configuration>

MapReduce 本地目录是 Hadoop 用来存储所用临时文件的位置。在 HADOOP_HOME/conf/mapred-site.xml中添加 JobTracker 的位置。Hadoop 将用这个地址来管理作业。最后一个属性设置每个节点最大的map任务数,该值通常与(CPU)核数相同。

<configuration>

<property>

<name>mapred.job.tracker</name>

<value>MASTER_NODE:9001</value>

</property>

<property>

<name>mapred.local.dir</name>

<value>HADOOP_DATA_DIR/local</value>

</property>

<property>

<name>mapred.tasktracker.map.tasks.maximum</name>

<value>8</value>

</property>

</configuration>

8. 要格式化新的HDFS文件系统,需要在Hadoop的NameNode(主节点)上运行以下命令。如果在前一节中已经完成了HDFS安装,可以跳过这一步。

>bin/hadoopnamenode –format

...

/Users/srinath/playground/hadoop-book/hadoop-temp/dfs/name has

been successfully formatted.

12/04/09 08:44:51 INFO namenode.NameNode: SHUTDOWN_MSG:

/************************************************************

SHUTDOWN_MSG: Shutting down NameNode at Srinath-s-MacBook-Pro.

local/172.16.91.1

************************************************************/

9. 在主节点上,将工作目录跳转到HADOOP_HOME,并运行以下命令:

>bin/start-dfs.sh

startingnamenode, logging to /root/hadoop-setup-srinath/hadoop-1.0.0/libexec/../logs/hadoop-root-namenode-node7.beta.out

209.126.198.72: starting datanode, logging to /root/hadoop-setupsrinath/hadoop-1.0.0/libexec/../logs/hadoop-root-datanode-node7.beta.out

209.126.198.71: starting datanode, logging to /root/hadoop-setupsrinath/hadoop-1.0.0/libexec/../logs/hadoop-root-datanode-node6.beta.out

209.126.198.72: starting secondarynamenode, logging to /root/hadoop-setup-srinath/hadoop-1.0.0/libexec/../logs/hadoop-root-secondarynamenode-node7.beta.out

>bin/start-mapred.sh

startingjobtracker, logging to /root/hadoop-setup-srinath/hadoop-1.0.0/libexec/../logs/hadoop-root-jobtracker-node7.beta.out

209.126.198.72: starting tasktracker, logging to /root/hadoop-setup-srinath/hadoop-1.0.0/libexec/../logs/hadoop-roottasktracker-node7.beta.out

209.126.198.71: starting tasktracker, logging to /root/hadoop-setup-srinath/hadoop-1.0.0/libexec/../logs/hadoop-roottasktracker-node6.beta.out

10. 在主节点和从节点上,通过 ps | grep java 命令(如果你使用的是 Linux)或通过任务管理器(如果你使用的是Windows)验证部署后的进程列表是否已经正常启动。主节点会列出四个进程——NameNode、DataNode、JobTracker和TaskTracker,从节点有DataNode和TaskTracker。

11. 浏览NameNode和JobTracker的Web监控页面。

□ NameNode:http://MASTER_NODE:50070/。

□ JobTracker:http://MASTER_NODE:50030/。

12. 你可以在${HADOOP_HOME}/logs下找到日志文件。

13. 通过使用HDFS命令行列出文件的方式,确认HDFS安装正确。

bin/hadoopdfs -ls /

Found 2 items

drwxr-xr-x - srinathsupergroup 0 2012-04-09 08:47 /Users

drwxr-xr-x - srinathsupergroup 0 2012-04-09 08:47 /tmp

工作原理

正如本章简介中所描述的,Hadoop的安装包括HDFS节点、JobTracker节点和工作节点。当我们启动NameNode时,它通过 HADOOP_HOME/slaves文件查找DataNode配置,并在启动时通过SSH在远程服务器上启动DataNode。同样,当我们启动JobTracker时,它通过HADOOP_HOME/slaves文件找到TaskTracker配置,进而启动TaskTracker。

更多参考

在下一节中,我们将讨论如何使用分布式环境执行前面提及的WordCount程序。之后的几节将讨论如何使用MapReduce的监控UI监控分布式Hadoop的安装。

1.9 在分布式集群环境中运行WordCount程序

本节将描述如何在分布式集群中运行作业。

准备工作

启动Hadoop集群。

操作步骤

现在让我们在分布式的Hadoop环境中运行WordCount示例程序。

1. 把你的Hadoop 发行版目录的 README.txt文件复制到HDFS 文件系统的/data/input1位置,作为我们前一节中编写的WordCountMapReduce示例的输入数据。

>bin/hadoopdfs -mkdir /data/

>bin/hadoopdfs -mkdir /data/input1

>bin/hadoopdfs -put README.txt /data/input1/README.txt

>bin/hadoopdfs -ls /data/input1

Found 1 items

-rw-r--r-- 1 srinathsupergroup  1366 2012-04-09 08:59 /

data/input1/README.txt

2. 现在,让我们在HADOOP_HOME目录下运行WordCount示例。

>bin/hadoop jar hadoop-examples-1.0.0.jar wordcount /data/input1/data/output1

12/04/09 09:04:25 INFO input.FileInputFormat: Total input paths to process : 1

12/04/09 09:04:26 INFO mapred.JobClient: Running job:

job_201204090847_0001

12/04/09 09:04:27 INFO mapred.JobClient: map 0% reduce 0%

12/04/09 09:04:42 INFO mapred.JobClient: map 100% reduce 0%

12/04/09 09:04:54 INFO mapred.JobClient: map 100% reduce 100%

12/04/09 09:04:59 INFO mapred.JobClient: Job complete:

job_201204090847_0001

...

3. 运行下面的命令可列出输出目录的内容,并查看运行结果。

>bin/hadoopdfs -ls /data/output1

Found 3 items

-rw-r--r-- 1 srinathsupergroup 0 2012-04-09 09:04 /data/output1/_SUCCESS

drwxr-xr-x - srinathsupergroup 0 2012-04-09 09:04 /data/output1/_logs

-rw-r--r-- 1 srinathsupergroup 1306 2012-04-09 09:04 /data/output1/part-r-00000

>bin/hadoopdfs -cat /data/output1/*

(BIS), 1

(ECCN) 1

(TSU) 1

(see 1

5D002.C.1, 1

740.13) 1

工作原理

分布式环境的Hadoop作业提交方式与本地安装的Hadoop作业提交方式相似,如1.3节所描述的那样。然而,有两点主要的不同。

首先,Hadoop将作业的输入数据和作业产生的输出数据都存储在HDFS文件系统中。因此,我们使用第1步将输入文件存储在HDFS文件系统中,使用第3步从HDFS文件系统中读取输出文件。

其次,提交作业时,本地Hadoop安装模式将作业放在本地JVM上执行。然而,分布式集群将作业提交给JobTracker,并且使用分布式Hadoop集群中的节点执行该作业。

更多参考

可以通过HDFS监控UI查看WordCount应用程序的结果,如1.6节所描述的那样。同样,也可以像1.10节介绍的那样查看关于WordCount作业的统计信息。

1.10 使用MapReduce监控UI

本节传授如何使用Hadoop的监控Web控制台来验证Hadoop的安装,以及如何监控Hadoop集群的每个部分的分配和使用。

操作步骤

现在让我们来访问Hadoop的监控Web控制台。

1. 使用浏览器访问http://MASTER_NODE:50030/,其中MASTER_NODE是主节点的IP地址。

2. 图1-6所示的网页显示了MapReduce安装的当前状态,包括正在运行和已经完成的作业。

工作原理

Hadoop的监控UI可让用户访问Hadoop配置的JobTracker,并且访问到不同的节点的安装、配置和使用信息。例如,用户可以使用UI看到当前正在运行的作业和与作业相关的日志。

注释

[1]. 技术上,secondary NameNode的功能描述有误,它并不是用来替代NameNode的。——译者注

[2]. 原书有误。——译者注

第2章 HDFS进阶

本章将学习以下内容:

□ HDFS基准测试

□ 添加一个新的DataNode

□ DataNode下架

□ 使用多个磁盘/卷以及限制HDFS的磁盘使用

□ 设置HDFS块大小

□ 设置文件的冗余因子

□ 使用HDFS的Java API

□ 使用HDFS的CAPI(libhdfs)

□ 挂载HDFS(Fuse-DFS)

□ 在HDFS中合并文件

2.1 简介

Hadoop分布式文件系统(Hadoop Distributed File System,HDFS)被设计成适合运行在低廉的通用硬件上的面向块结构的分布式文件系统。HDFS 支持海量数据存储,并提供高吞吐量的数据访问。HDFS 通过跨多个节点的冗余方式存储文件数据,以确保容错性和高聚合带宽。

HDFS是Hadoop MapReduce计算默认使用的分布式文件系统。Hadoop在处理存储在HDFS上的数据时支持数据本地化感知。然而,HDFS也可以用作一个通用的分布式文件系统。HDFS 架构主要由一个用于处理文件系统元数据的中央 NameNode 以及很多个用于存储真实数据块的DataNode组成。HDFS数据块通常是粗粒度的,适合存储大数据产品。

1.5节和第1章中的其他各节说明了如何部署HDFS,并对 HDFS的基本操作给出了一个概述。本章将学习一组精心挑选的高级HDFS 操作,在使用Hadoop MapReduce 进行大规模数据处理时,这些操作将十分有用,同时,也适用于使用HDFS作为一个独立的分布式文件系统用于非MapReduce场景。

2.2 HDFS基准测试

运行基准测试程序,可以很好地验证 HDFS 集群是否已如预期般正确设置并执行。DFSIO是一个Hadoop自带的基准测试,可以用来分析一个HDFS集群的I/O性能。该部分展示了如何使用DFSIO来对HDFS集群的读取和写入性能进行基准测试。

准备工作

在运行这些基准程序之前,必须安装和部署HDFS和MapReduce。导出HADOOP_HOME环境变量,将其指向Hadoop安装根目录:

>export HADOOP_HOME = /../hadoop-1.0.4

该基准测试程序在$HADOOP_HOME/hadoop-*test.jar文件中。

操作步骤

下列步骤显示了如何运行写入性能基准测试。

1. 在$HADOOP_HOME目录下执行以下命令来测试写入性能的基准程序。-nrFiles参数指定了文件数量,同时-fileSize参数指定了以MB为单位的文件大小。

>bin/hadoop jar $ HADOOP_HOME/hadoop-test- *.JAR TestDFSIO -write-nrFiles 5 -CfileSize 100

2. 基准测试程序会将日志写入控制台,同时将日志追加到一个名为TestDFSIO_results.log的文件中。可以使用-resFile参数提供自定义的结果文件名。

下列步骤显示了如何执行测试读性能的基准测试。

1. 读性能基准测试采用步骤 1 中的写性能基准测试创建的文件。因此,写性能基准测试应该在运行读性能基准测试之前执行,并且写基准测试所创建的文件必须存储在HDFS上,以便读基准测试运行。

2. 执行下面的命令运行读基准测试。读基准测试也会将结果写入控制台,并将其结果追加到一个与写基准测试类似的日志文件。

>bin/ hadoop jar $ HADOOP_HOME/hadoop-test- *.jar TestDFSIO -read-nrFiles5 -CfileSize 100

要清理这些基准测试生成的结果文件,可以使用以下命令:

>bin/hadoop jar $HADOOP_HOME hadoop-test-*.jar TestDFSIO –clean

工作原理

DFSIO实际是执行一个MapReduce作业,其中map任务并行读写文件,而reduce任务则被用来收集和归纳性能数据。

更多参考

在运行这些基准测试时,同步观察监控系统,可以帮助你更轻松地识别瓶颈所在。

延伸阅读

□ 参见3.3节。

2.3 添加一个新的DataNode

本节将展示如何在不重启整个集群的情况下将新节点添加到现有的HDFS集群中,以及增加新的节点后,如何强制HDFS重新达到平衡。

准备工作

请按照下列步骤向HDFS集群中添加DataNode节点。

1. 在新节点上安装Hadoop,并且复制现有的Hadoop 集群的配置文件。可以使用 rsync从另一个节点复制Hadoop配置。例如:

>rsync -a <master_node_ip>:hadoop-1.0.x/conf $HADOOP_HOME/conf

2. 确保 Hadoop/HDFS 集群的主节点可以对新节点进行 SSH 免密码登录。如果不打算使用bin/*.sh脚本从主节点启动/停止集群,那么可以选择SSH免登录设置。

操作步骤

下面的步骤将展示如何将新的DataNode添加到现有的HDFS集群。

1. 将新节点的IP或DNS地址添加到主节点的$HADOOP_HOME/conf/slaves文件。

2. 通过使用以下命令在新添加的从节点上启动DataNode进程。

>bin/hadoop-deamon.sh start datanode

也可以使用$HADOOP_HOME/bin/start-dfs.sh 脚本从主节点启动新加入的从节点的DataNode守护进程。如果要向集群中添加多个新的DataNode,那么这样做会非常有益。

3. 在新加的从节点上,检查$HADOOP_HOME/logs/hadoop-*-datanode-*.log是否有任何错误信息。

前面的步骤既适用于添加新节点,又适用于重新加入的因崩溃而重新启动的节点。

更多参考

同样,你也可以添加一个新的节点到Hadoop MapReduce集群。

1. 要在新节点上启动TaskTracker必须使用以下命令:

>bin/hadoop-deamon.sh start tasktracker

2. 在新加的从节点上,检查$HADOOP_HOME/logs/hadoop-*-tasktracker-*.log 是否有任何错误信息。

HDFS再平衡

当您添加新节点时,HDFS不会自动重新平衡。然而,HDFS提供了一个手动调用的重新平衡(reblancer)工具。这个工具将整个集群中的数据块分布调整到一个可人工配置的百分比阈值。如果在其他现有的节点上有空间存储问题,再平衡将是非常有益的。

1. 执行以下命令。可选参数-threshold 指定了磁盘容量的余量百分比,用来判定一个节点的利用率是过低还是过高。一个利用不足的数据节点其利用率低于平均利用率−阈值。过度利用的数据节点其利用率高于平均利用率+阈值。该参数设置的越小,整个集群越平衡,但会花费更多的时间进行再平衡操作。默认阈值为10%。

>bin/start-balancer.sh –threshold 15

2. 再平衡操作可以通过执行bin/stop-balancer.sh命令手动停止。

3. 再平衡操作的日志信息存储在$HADOOP_HOME/logs/hadoop-*-balancer*.out 文件中。

延伸阅读

□ 参见2.4节。

2.4 DataNode下架

有些时候你可能想让一个HDFS集群的一个或多个数据节点下架。本节展示了如何优雅地让使用中的DataNode下架而不会导致数据丢失,而且无需重新启动集群。

操作步骤

下列步骤显示了如何让数据节点优雅地下架。

1. 如果集群没有排除文件配置,则需要向集群中添加一个排除文件(exclude file)。在NameNode上创建一个空文件,并且通过添加以下属性从conf/hdfs-site.xml文件指向它。

<property>

<name>dfs.hosts.exclude</name>

<value>[FULL_PATH_TO_THE_EXCLUDE_FILE]</value>

<description>Names a file that contains a list of hosts thatare

not permitted to connect to the namenode. The full pathname of

the file must be specified. If the value is empty, no hosts are

excluded.</description>

</property>

2. 将要下架的节点的主机名添加到exclude文件中。

3. 运行下列命令以重新加载NameNode 的配置。这将启动下架过程。下架过程可能需要相当一段时间,因为它需要确保数据块的复制操作没有影响集群的其他任务。

>bin/hadoopdfsadmin -refreshNodes

4. 下架进度显示在HDFS中用户界面下的Decommissioning Nodes页面。也可以使用下面的命令监控下架进度。不要关闭这些下架中节点,直到下架完成。

>bin/hadoopdfsadmin -report

...

...

Name: myhost:50010

Decommission Status : Decommission in progress

Configured Capacity: ...

...

5. 当想要把这些节点重新添加回集群时,可以从 exclude 文件中删除节点,执行

bin/Hadoop dfsadmin –refreshNodes命令。

6. 下架过程可以通过从 exclude 文件中删除该节点的名称、然后执行 bin/hadoopd dfsadmin -refreshNodes命令来停止。

工作原理

在节点下架时,HDFS 会将该节点中的块复制到集群中的其他节点。下架可能是一个非常缓慢的过程,因为HDFS故意使它缓慢地运行,以避免集群过载。如果直接关闭节点,而不采用下架,可能会导致数据丢失。

下架完成后,将不再允许exclude文件所提及的节点与NameNode通信。

延伸阅读

□ 参见2.3节中的“HDFS再平衡”。

2.5 使用多个磁盘/卷以及限制HDFS的磁盘使用情况

Hadoop支持为DataNode数据目录指定多个操作系统目录。此功能使我们能够利用多个磁盘/卷来存储DataNode的数据块。Hadoop将尝试在每个目录中存储等量的数据。Hadoop也支持限制HDFS使用的磁盘空间数量。

操作步骤

下面的步骤将展示如何添加多个磁盘卷。

1. 在每个卷中创建HDFS的数据存储目录。

2. 在$HADOOP_HOME/conf/hdfs-site.xml 中,提供了一个逗号分隔的列表,对应于dfs.data.dir目录下的每个卷的数据存储位置的目录。

<property>

<name>dfs.data.dir</name>

<value>/u1/hadoop/data,/u2/hadoop/data</value>

</property>

3. 为了限制 HDFS 的磁盘使用情况,将下面的属性添加到$HADOOP_HOME/conf/hdfs-site.xml中,以预留空间给非DFS使用。该值指定HDFS每卷不能使用的字节数。

<property>

<name>dfs.datanode.du.reserved</name>

<value>60 00000000</value>

<description>Reserved space in bytes per volume. Always leave

this much space free for non dfs use.

</description>

</property>

2.6 设置HDFS块大小

HDFS 跨集群存储文件时,会把文件切分成粗粒度的、大小固定的块。默认的 HDFS块大小为64 MB。数据产品的块大小会影响文件系统操作的性能,如果存储和处理非常大的文件,那么较大的块大小会更高效。数据产品的块大小会影响MapReduce计算的性能,因为Hadoop的默认行为是为输入文件中的每个数据块创建一个map任务。

操作步骤

1. 要使用 NameNode 的配置文件来设置 HDFS 的块大小,需要在$HADOOP_HOME/conf/hdfs-site.xml中添加或修改以下参数。块的大小用字节数提供。这种修改不会改变那些已经存储在HDFS中的文件的块大小。只有在参数修改后新复制的文件才有新的块大小。

<property>

<name>dfs.block.size</name>

<value>134217728</value>

</property>

2. 要为特定的文件路径指定HDFS 块大小,你可以在命令行上载文件时,通过如下参数指定块大小:

>bin/hadoopfs -Ddfs.blocksize=134217728 -put data.in /user/foo

更多参考

还可以使用HDFS Java API在创建文件时指定块大小。

publicFSDataOutputStream create(Path f,boolean overwrite, int bufferSize, short replication,long blockSize)

可以使用 fsck命令来查找特定文件路径的块大小和数据块在 HDFS 中的存储位置。也可以通过从HDFS的监控控制台浏览文件系统,找到这些信息。

>bin/hadoopfsck /user/foo/data.in -blocks -files -locations

...

/user/foo/data.in 215227246 bytes, 2 block(s): ...

0. blk_6981535920477261584_1059len=134217728 repl=1 [hostname:50010]

1. blk_-8238102374790373371_1059 len=81009518 repl=1 [hostname:50010]

...

延伸阅读

□ 参见2.7节。

2.7 设置文件冗余因子

HDFS 跨集群存储文件时,会把文件切分成粗粒度的、大小固定的块。出于容错的目的,这些粗粒度的数据块会被复制到不同的DataNode中。数据块的冗余有助于增加数据本地化MapReduce计算的能力,同时也可以增加总的数据访问带宽。减少冗余因子则有助于节省HDFS上的存储空间。

HDFS冗余因子(HDFS replication factor)是文件级属性,可以基于每个文件进行单独配置。本节将展示如何通过改变HDFS部署的默认冗余因子来影响以后创建的新文件,如何在创建HDFS文件的时候指定自定义冗余因子,以及如何改变现有的HDFS文件的冗余因子。

操作步骤

1. 要使用 NameNode 的配置文件来设置文件的冗余因子,需要添加或修改$HADOOP_HOME/conf/hdfs-site.xml 中的 dfs.replication 属性。这种修改不会改变那些HDFS中已有的文件的冗余因子。新的冗余因子只会影响在参数修改后新复制的文件。

<property>

<name>dfs.replication</name>

<value>2</value>

</property>

2. 也可以在上传文件时在命令行中设置文件的冗余因子,如下所示:

>bin/hadoopfs -D dfs.replication=1 -copyFromLocal non-critical-file.txt /user/foo

3. 使用setrep命令可以改变HDFS中已有的文件或文件路径的冗余因子。

>bin/hadoopfs -setrep 2 non-critical-file.txt

Replication 3 set: hdfs://myhost:9000/user/foo/non-critical-file.txt

工作原理

setrep命令的语法如下:

hadoopfs -setrep [-R] <path>

使用setrep命令的<path>参数可以指定需要改变冗余因子的HDFS路径。使用-R选项可以递归地为一个目录中的所有文件和目录设置冗余因子。

更多参考

使用ls命令列出文件时,会显示文件的冗余因子。

>bin/hadoopfs -ls

Found 1 item

-rw-r--r--2foo supergroup ... /user/foo/non-critical-file.txt

在HDFS监控用户界面上浏览文件时,也会显示文件的冗余因子。

延伸阅读

□ 参见2.6节。

2.8 使用HDFS的Java API

HDFS Java API可用于任何Java程序与HDFS交互。该API使我们能够从其他Java程序中利用到存储在HDFS中的数据,也能够使用其他非Hadoop的计算框架处理该数据。有时,可能也会遇到要直接从MapReduce应用程序中访问HDFS的用例。但是,如果你是在HDFS中直接通过map或reduce任务写入或修改文件,那么你要知道,这样做实际上违反了MapReduce构架的无副作用的本质,可能会导致某些用例出现数据一致性问题。

准备工作

设置HADOOP_HOME环境变量指向Hadoop的安装根目录。

操作步骤

下列步骤显示了如何使用HDFS的Java API来对HDFS集群使用Java程序执行文件系统操作。

1. 下面的示例程序会在 HDFS 中创建一个新文件,写一些文本内容到新建文件,并从HDFS中读回该文件:

importjava.io.IOException;

importorg.apache.hadoop.conf.Configuration;

importorg.apache.hadoop.fs.FSDataInputStream;

importorg.apache.hadoop.fs.FSDataOutputStream;

importorg.apache.hadoop.fs.FileSystem;

importorg.apache.hadoop.fs.Path;

public class HDFSJavaAPIDemo {

public static void main(String[] args) throws IOException {

Configuration conf = new Configuration();

FileSystemfs = FileSystem.get(conf);

System.out.println(fs.getUri());

Path file = new Path("demo.txt");

if (fs.exists(file)) {

System.out.println("File exists.");

} else {

// Writing to file

FSDataOutputStreamoutStream = fs.create(file);

outStream.writeUTF("Welcome to HDFS Java API!!!");

outStream.close();

}

// Reading from file

FSDataInputStreaminStream = fs.open(file);

String data = inStream.readUTF();

System.out.println(data);

inStream.close();

fs.close();

}

2. 将上面的程序编译并打包成一个JAR包。解压本章提供的源码包,转到HDFS_Java_API文件夹,然后运行Ant构建即可。HDFSJavaAPI.jar文件将在build文件夹中被创建。

>cd HDFS_java_API

>ant

可以使用下面的Ant构建文件来编译上面的示例程序:

<project name="HDFSJavaAPI" default="compile" basedir=".">

<property name="build" location="build"/>

<property environment="env"/>

<path id="hadoop-classpath">

<filesetdir="${env.HADOOP_HOME}/lib">

<include name="**/*.jar"/>

</fileset>

<filesetdir="${env.HADOOP_HOME}">

<include name="**/*.jar"/>

</fileset>

</path>

<target name="compile">

<mkdirdir="${build}"/>

<javacsrcdir="src" destdir="${build}">

<classpathrefid="hadoop-classpath"/>

</javac>

<jar jarfile="HDFSJavaAPI.jar" basedir="${build}"/>

</target>

<target name="clean">

<delete dir="${build}"/>

</target>

</project>

3. 可以在Hadoop上使用以下命令执行上述示例。使用hadoop脚本运行示例,可以确保它采用了当前配置的HDFS,并从Hadoop的类路径中加载了必要的依赖。

>bin/hadoop jar HDFSJavaAPI.jar HDFSJavaAPIDemo

hdfs://yourhost:9000

Welcome to HDFS Java API!!!

4. 使用ls命令列出新创建的文件:

>/bin/hadoopfs -ls

Found 1 items

-rw-r--r-- 3 foosupergroup  20 2012-04-27 16:57 /user/

foo/demo.txt

工作原理

为了以编程方式与HDFS进行交互,首先需要得到当前配置文件系统的句柄。实例化一个Configuration对象,并获得一个Hadoop环境中的 FileSystem句柄,它将指向当前环境的HDFS NameNode。有几种替代配置FileSystem对象的方法,将在本节的“更多参考”中的“配置文件系统对象”中讨论。

Configuration conf = new Configuration();

FileSystemfs = FileSystem.get(conf);

FileSystem.create(filePath)方法会在指定的路径创建一个新的文件,并提供一个到新创建的文件的 FSDataOutputStream 对象。FSDataOutputStream 封装了java.io.DataOutputStream,并允许程序向文件中写入基本Java数据类型。如果该文件存在,FileSystem.Create()方法将覆盖该文件。在这个例子中,该文件将在HDFS中相对于用户的主目录进行创建,产生类似/user/<user_name>/demo.txt的路径。

Path file = new Path("demo.txt");

FSDataOutputStreamoutStream = fs.create(file);

outStream.writeUTF("Welcome to HDFS Java API!!!");

outStream.close();

FileSystem.open(filePath)打开给定文件的FSDataInputStream。FSDataInputStream封装了java.io.DataInputStream,允许程序从文件中读取基本Java数据类型。

FSDataInputStreaminStream = fs.open(file);

String data = inStream.readUTF();

System.out.println(data);

inStream.close();

更多参考

HDFS的JavaAPI支持的文件系统操作比我们在上面的示例中用到的多得多。完整的API文档可以在 http://hadoop.apache.org/common/docs/current/api/org/apache/hadoop/fs/FileSystem.html页面找到。

配置文件系统对象

我们也可以在Hadoop的环境之外使用HDFS的Java API。当这样做时,必须显式配置HDFS的NameNode和端口。以下是几种进行该项配置的方法。

□ 可以通过如下方式在获得FileSystem对象之前加载Configuration对象的配置文件。但需要确保将所有的Hadoop和依赖库都添加到类路径中。

Configuration conf = new Configuration();

conf.addResource(new Path(".../hadoop/conf/core-site.xml"));

conf.addResource(new Path(".../hadoop/conf/hdfs-site.xml"));

FileSystemfileSystem = FileSystem.get(conf);

□ 还可以通过如下方式指定NameNode和端口。将NAMENODE_HOSTNAME和PORT替换为HDFS安装的NameNode的主机名和端口。

Configuration conf = new Configuration();

conf.set("fs.default.name", "hdfs://NAMENODE_HOSTNAME:PORT");

FileSystemfileSystem = FileSystem.get(conf);

HDFS的文件系统API,是一种支持多个文件系统的抽象。如果上述程序无法找到有效的 HDFS 配置,它将会指向本地文件系统,而不是 HDFS。可以通过如下方式使用getUri()函数识别 FileSystem对象的当前文件系统。在使用正确的HDFS配置文件的情况下,会返回hdfs://your_namenode:port,在使用本地文件系统的情况下,则会返回file:///。

fileSystem.getUri();

获取文件的数据块列表

FileSystem对象的getFileBlockLocations()函数,可以用来获取存储在HDFS中的文件数据块的列表,同时也可以获取存储块的主机名和块的偏移量。如果计划使用Hadoop MapReduce之外的其他框架来执行文件数据的任何数据本地化操作,那么这些信息将会非常有用。

FileStatusfileStatus = fs.getFileStatus(file);

BlockLocation[] blocks = fs.getFileBlockLocations(

fileStatus, 0, fileStatus.getLen());

延伸阅读

□ 参见2.9。

2.9 使用HDFS的C API(libhdfs)

libhdfs是一个原生共享库,提供了一套C API,允许非Java程序与HDFS进行交互。libhdfs使用JNI通过Java与HDFS进行交互。

准备工作

目前的Hadoop发行版中包含了为32位和64位Linux操作系统预编译的libhdfs库。如果你的操作系统与预编译库不兼容,则可能需要下载 Hadoop 的标准发行版并从源代码编译libhdfs库。有关编译libhdfs库的信息请参见2.10节。

操作步骤

下列步骤显示了如何在HDFS环境下使用HDFS的CAPI执行操作。

1. 下面的示例程序会在 HDFS 中创建一个新文件,向新建文件中写入一些文本信息,并从HDFS读回该文件。用HDFS集群中NameNode的相关值替换NAMENODE_HOSTNAME和端口变量。该hdfs_cpp_demo.c源文件中的源代码包位于该文件夹的HDFS_C_API目录中。

#include "hdfs.h"

int main(intargc, char **argv) {

hdfsFSfs =hdfsConnect( "NAMENODE_HOSTNAME,PORT");

if (!fs) {

fprintf(stderr, "Cannot connect to HDFS.\n");

exit(-1);

}

char* fileName = "demo_c.txt";

char* message = "Welcome to HDFS C API!!!";

int size = strlen(message);

int exists = hdfsExists(fs, fileName);

if (exists > -1) {

fprintf(stdout, "File %s exists!\n", fileName);

}else{

// Create and open file for writing

hdfsFileoutFile = hdfsOpenFile(fs, fileName, O_WRONLY|O_CREAT, 0, 0, 0);

if (!outFile) {

fprintf(stderr, "Failed to open %s for writing!\n", fileName);

exit(-2);

}

// write to file

hdfsWrite(fs, outFile, (void*)message, size);

hdfsCloseFile(fs, outFile);

}

// Open file for reading

hdfsFileinFile = hdfsOpenFile(fs, fileName, O_RDONLY, 0, 0, 0);

if (!inFile) {

fprintf(stderr, "Failed to open %s for reading!\n", fileName);

exit(-2);

}

char* data = malloc(sizeof(char) * size);

// Read from file.

tSizereadSize = hdfsRead(fs, inFile, (void*)data, size);

fprintf(stdout, "%s\n", data);

free(data);

hdfsCloseFile(fs, inFile);

hdfsDisconnect(fs);

return 0;

}

2. 通过使用如下 gcc命令编译上面的程序。当编译时,需要链接 libhdfs和 JVM 库。因此,还必须包括Java安装路径的JNI头文件。一个示例编译命令如下所示。将ARCH和架构依赖的路径替换成当前系统的路径。

>gcchdfs_cpp_demo.c \

-I $HADOOP_HOME/src/c++/libhdfs \

-I $JAVA_HOME/include \

-I $JAVA_HOME/include/linux/ \

-L $HADOOP_HOME/c++/ARCH/lib/ \

-L $JAVA_HOME/jre/lib/ARCH/server\

-l hdfs -ljvm -o hdfs_cpp_demo

3. 重置环境变量 CLASSPATH,将其指向 Hadoop 的依赖环境。一种保险的方法是将$HADOOP_HOME和$HADOOP_HOME/lib中的所有jar文件全部包括在环境变量中。

export CLASSPATH=$HADOOP_HOME/hadoop-core-xx.jar:...

Ant构建脚本生成类路径

在2.8节步骤2中给出的build文件的末尾,添加下面的Anttarget。本章源码包的HDFS_C_API文件夹中提供了修改后的build.xml脚本。

<target name="print-cp">

<property name="classpath"

refid="hadoop-classpath"/>

<echo message="classpath= ${classpath}"/>

</target>

用ant print-cp执行Ant构建,之后会生成一个包含$HADOOP_HOME和$HADOOP_HOME/lib中的所有jar文件名的字符串。复制这个字符串导出到CLASSPATH环境变量中。

4. 执行程序。

>LD_LIBRARY_PATH=$HADOOP_HOME/c++/ARCH/lib:$JAVA_HOME/jre/lib/ARCH/server./hdfs_cpp_demo

Welcome to HDFS C API!!!

工作原理

首先,我们通过hdfsConnect命令输入NameNode的主机名(或IP地址)和端口来连接到一个HDFS集群。hdfsConnectAsUser命令可以作为一个特定的用户连接到一个HDFS集群。

hdfsFSfs =hdfsConnect("NAMENODE_HOSTNAME",PORT);

使用hdfsOpenFile命令新建文件,并获得新新建文件的句柄。O_WRONLY | O_CREAT标志表示新建一个文件或重写现有文件,并用只写模式打开它。其他支持的标志还有O_RDONLY和O_APPEND。该hdfsOpenFile命令的第四、第五和第六个参数分别表示进行读/写操作的缓冲区大小、块的冗余因子和新创建文件的块大小。如果想使用这三个参数的默认值,可以将它们指定为0。

hdfsFileoutFile = hdfsOpenFile(fs, fileName,flags, 0, 0, 0);

该 hdfsWrite指令将提供的数据写入到 outFile句柄指定的文件中。数据大小需要以字节数为单位指定。

hdfsWrite(fs, outFile, (void*)message, size);

hdfsRead命令从inFile指定的文件中读取数据。需要提供以字节为单位的缓冲区大小作为第四个参数。hdfsRead命令返回文件读取的实际字节数,该数量可能小于缓冲区大小。如果想要确保从文件中读取一定的字节数,最好是在循环内使用 hdfsRead 命令,直到读完了指定的字节数为止。

char* data = malloc(sizeof(char) * size);

tSizereadSize = hdfsRead(fs, inFile, (void*)data, size);

更多参考

HDFS 的 C API(libhdfs)支持的文件系统操作比前面示例中用到的多。请参见$HADOOP_HOME/src/ c++/libhdfs/hdfs.h头文件获得更多有关的详细信息。

使用HDFS的配置文件配置

还可以使用HDFS的配置文件来告诉libhdfsNameNode的主机名和端口号,而不是通过hdfsConnect命令以参数的方式传入。

1. 在hdfsConnect命令中,将NameNode的主机名和端口号改为"default"和0。(将主机名设置为NULL将使libhdfs使用本地文件系统)。

hdfsFSfs = hdfsConnect("default",0);

2. 将HDFS安装的conf目录添加到CLASSPATH环境变量中。

export CLASSPATH=$HADOOP_HOME/hadoop-core-xx.jar:...:$HADOOP_HOME/conf

延伸阅读

□ 参见2.8节和2.10节。

2.10 挂载HDFS(Fuse-DFS)

Fuse-DFS项目使我们能够在Linux上挂载HDFS(也支持许多其他版本的Unix)作为标准的文件系统。这样做,可以允许任何程序或用户使用类似于传统的文件系统的方式访问HDFS和与HDFS交互。

准备工作

系统中必须安装以下软件:

□ ApacheAnt(http://ant.apache.org/);

□ Fuse 和 fuse 开发包。Fuse 开发文件可以通过 Redhat/Fedora 安装 fuse-devel RPM或者Debian/Ubuntu安装libfuse-dev软件包的方式获得。

JAVA_HOME必须设置为指向JDK的环境,而不是JRE。

要挂载HDFS文件系统,还需要具备操作系统节点的root权限。

以下攻略假定你已经预先内置了libhdfs库。Hadoop中包含为Linux x86_64/i386平台预编译的libhdfs库。如果使用其他平台,首先需要参考本节“更多参考”小节中的“构建libhdfs”,以正确构建libhdfs库。

操作步骤

下列步骤显示了如何挂载HDFS文件系统作为一个Linux的标准文件系统。

1. 转到$ HADOOP_HOME并创建一个名为build的新目录。

>cd $HADOOP_HOME

>mkdir build

2. 创建符号链接,链接到build目录里面的libhdfs库。

>ln -s c++/Linux-amd64-64/lib/ build/libhdfs

3. 将C++目录复制到build文件夹。

>cp -R c++/ build/

4. 在$HADOOP_HOME下执行以下命令,建立fuse-dfs。此命令将在build/contrib/fusedfs/目录下生成fuse_dfs和fuse_dfs_wrapper.sh文件。

>ant compile-contrib -Dlibhdfs=1 -Dfusedfs=1

如果构建失败,并显示类似 undefined reference to 'fuse_get_context'的信息,则需要将以下内容追加到 src/contrib/fuse-dfs/src/Makefile.am文件的末尾:

fuse_dfs_LDADD =-lfuse-lhdfs-ljvm-LM

5. 验证 fuse_dfs_wrapper.sh 中的路径信息并更正它们。可能需要更改以下行的libhdfs路径:

export LD_LIBRARY_PATH=$JAVA_HOME/jre/lib/$OS_ARCH/server:$HADOOP_HOME/build/libhdfs/:/usr/local/lib

6. 如果已经存在,则需要在/etc/fuse.conf文件中注释掉user_allow_other行。

7. 创建一个目录作为挂载点:

>mkdir /u/hdfs

8. 在 build/contrib/fuse-dfs/目录下执行以下命令。而且,必须以 root 权限执行此命令。确保在根环境下也能正确设置 HADOOP_HOME和 JAVA_HOME环境变量。可选的-d参数用于开启调试模式。当你第一次运行它的时候,将在调试模式下运行以下命令,方便识别任何错误信息。rw 参数挂载文件系统为可读写(ro 为只读)。-oserver 必须指向NameNode的主机名。-oport应提供NameNode的端口号。

>chmoda+x fuse_dfs_wrapper.sh

>./fuse_dfs_wrapper.sh rw -oserver=localhost -oport=9000 /u/hdfs/-d

工作原理

Fuse-DFS是基于用户空间的文件系统进行构建的。FUSE项目(http://fuse.sourceforge. net/),致力于让用户能够实现用户空间的文件系统。Fuse-DFS使用libhdfs C API与HDFS文件系统交互。libhdfs使用JNI产生一个JVM,与配置的HDFS的NameNode进行通信。

更多参考

正如前面章节所述,使用Fuse-DFS,HDFS的许多实例可以挂载到不同的目录上。

构建libhdfs

为了构建libhdfs,必须在系统上安装以下软件:

□ ant-nodeps和ant-trax包;

□ automake包;

□ Libtool包;

□ zlib-devel包;

□ JDK 1.5——编译Apache Forrest的时候需要;

□ Apache Forrest(http://forrest.apache.org/)——建议使用0.8版本。

通过在$HADOOP_HOME下执行如下命令编译libhdfs:

>ant compile-c++-libhdfs -Dislibhdfs=1

通过执行以下命令将 libhdfs打包。使用-Djava5.home属性提供JDK 1.5 的路径。使用-Dforrest.home属性提供Apache Forrest的安装路径。

>ant package -Djava5.home=/u/jdk1.5 -Dforrest.home=/u/apache-forrest-0.8

检查 build/libhdfs 目录是否包含 libhdfs.*文件。如果没有,请将 build/c++/<your_architecture>/lib目录下的文件复制到build/libhdfs下。

>cp -R build/c++/<Your_OS_Architecture/lib>/ build/libhdfs

延伸阅读

□ 参见2.9节。

2.11 在HDFS中合并文件

本节将传授如何合并HDFS中的若干文件,以创建一个单独的文件。对于获取有多个输出部分结果的reducer的MapReduce作业的计算结果来说,这招非常有用。

操作步骤

HDFS的 getMerge命令可以将HDFS中给定路径下的文件,复制到本地文件系统的单个合并后的文件中。

>bin/hadoopfs -getmerge /user/foo/demofiles merged.txt

工作原理

getmerge命令的语法如下:

hadoopfs -getmerge<src><localdst> [addnl]

getmerge命令有三个参数。第一个参数——<src files>是HDFS路径,它包含要连接文件的 HDFS 目录。<dist file>是合并文件的本地文件名。addnl 为可选参数,表示是否需要在每一个合并后的结果文件末尾添加新行。

相关图书

Hadoop虚拟化
Hadoop虚拟化
大数据开发者权威教程:NoSQL、Hadoop组件及大数据实施
大数据开发者权威教程:NoSQL、Hadoop组件及大数据实施
Hadoop海量数据处理:技术详解与项目实战(第2版)
Hadoop海量数据处理:技术详解与项目实战(第2版)
Hadoop海量数据处理:技术详解与项目实战
Hadoop海量数据处理:技术详解与项目实战
Hadoop MapReduce性能优化
Hadoop MapReduce性能优化
Hadoop实战手册
Hadoop实战手册

相关文章

相关课程