天天看点

《Hadoop实战手册》一1.2 使用Hadoop shell命令导入和导出数据到HDFS

本节书摘来异步社区《hadoop实战手册》一书中的第1章,第1.2节,作者: 【美】jonathan r. owens , jon lentz , brian femiano 译者: 傅杰 , 赵磊 , 卢学裕 责编: 杨海玲,更多章节内容可以访问云栖社区“异步社区”公众号查看。

hdfs提供了许多shell命令来实现访问文件系统的功能,这些命令都是构建在hdfs filesystem api之上的。hadoop自带的shell脚本是通过命令行来执行所有操作的。这个脚本的名称叫做hadoop,通常安装在$hadoop_bin目录下,其中$hadoop_bin是hadoopbin文件完整的安装目录,同时有必要将$hadoop_bin配置到$path环境变量中,这样所有的命令都可以通过hadoop fs -command这样的形式来执行。

如果需要获取文件系统的所有命令,可以运行hadoop命令传递不带参数的选项fs。

《Hadoop实战手册》一1.2 使用Hadoop shell命令导入和导出数据到HDFS

这些按照功能进行命名的命令的名称与unix shell命令非常相似。使用help选项可以获得某个具体命令的详细说明。

《Hadoop实战手册》一1.2 使用Hadoop shell命令导入和导出数据到HDFS

在这一节中,我们将使用hadoop shell命令将数据导入hdfs中,以及将数据从hdfs中导出。这些命令更多地用于加载数据,下载处理过的数据,管理文件系统,以及预览相关数据。掌握这些命令是高效使用hdfs的前提。

准备工作

操作步骤

完成以下步骤,实现将weblog_entries.txt文件从本地文件系统复制到hdfs上的一个指定文件夹下。

1.在hdfs中创建一个新文件夹,用于保存weblog_entries.txt文件:

2.将weblog_entries.txt文件从本地文件系统复制到hdfs刚创建的新文件夹下:

3.列出hdfs上weblog_entries.txt文件的信息:

图像说明文字在hadoop处理的一些结果数据可能会直接被外部系统使用,可能需要其他系统做更进一步的处理,或者mapreduce处理框架根本就不符合该场景,任何类似的情况下都需要从hdfs上导出数据。下载数据最简单的办法就是使用hadoop shell。

4.将hdfs上的weblog_entries.txt文件复制到本地系统的当前文件夹下:

《Hadoop实战手册》一1.2 使用Hadoop shell命令导入和导出数据到HDFS

复制hdfs的文件到本地文件系统时,需要保证本地文件系统的空间可用以及网络连接的速度。hdfs中的文件大小在几个tb到几十个tb是很常见的。在1gbit网络环境下,从hdfs中导出10 tb数据到本地文件系统,最好的情况下也要消耗23个小时,当然这还要保证本地文件系统的空间是可用的。

下载本书的示例代码

工作原理

mkdir可以通过hadoop fs -mkdir path1 path2的形式来执行。例如,hadoop fs –mkdir /data/weblogs/12012012 /data/ weblogs/12022012将会在hdfs系统上分别创建两个文件夹/data/weblogs/12012012和/data/weblogs/12022012。如果文件夹创建成功则返回0,否则返回-1。

《Hadoop实战手册》一1.2 使用Hadoop shell命令导入和导出数据到HDFS

copyfromlocal可以通过hadoop fs –copyfromlocal localfilepath uri的形式来执行,如果uri的地址(指的是hdfs://filesystemname:9000这个串)没有明确给出,则默认会读取core-site.xml中的fs.default.name这个属性。上传成功返回0,否则返回-1。

copytolocal命令可以通过hadoop fs –copytolocal [-ignorecrc] [-crc] urilocal_file_path的形式来执行。如果uri的地址没有明确的给出,则默认会读取core-site.xml中的fs.default.name这个属性。copytolocal会执行crc(cyclic redundancy check)校验保证已复制的数据的正确性,一个失败的副本复制可以通过 参数–ignorecrc来强制执行,还可以通过-crc参数在复制文件的同时也复制crc校验文件。

更多参考

put命令与copyfromlocal类似,put更通用一些,可以复制多个文件到hdfs中,也能接受标准输入流。

任何使用copytolocal的地方都可以用get替换,两者的实现一模一样。

在使用mapreduce处理大数据时,其输出结果可能是一个或者多个文件。最终输出结果的文件个数是由mapred.reduce.tasks的值决定的。我们可以在jobconf类中通过setnumreducetasks()方法来设置这个属性,改变提交作业的reduce个数,每个reduce将对应输出一个文件。该参数是客户端参数,非集群参数,针对不同的作业应该设置不同的值。其默认值为1,意味着所有map(映射函数,以下都用map表示)的输出结果都将复制到1个reducer上进行处理。除非map输出的结果数据小于1 gb,否则默认的配置将不合适。reduce个数的设置更像是一门艺术而不是科学。在官方的文档中对其设置推荐的两个公式如下:

或者

假设你的集群有10个节点来运行task tracker,每个节点最多可以启动5个reduce槽位(通过设置tasktracker.reduce.tasks.maximum这个值来决定每个节点所能启动的最大reduce槽位数)对应的这个公式应该是0.95×10×4=47.5。因为reduce个数的设置必须是整数,所以需要进行四舍五入。

0.95可以保证在map结束后可以立即启动所有的reduce进行map结果的复制,只需要一波就可以完成作业。1.75使得运行比较快的reducer能够再执行第二波reduce,保证两波reduce就能完成作业,使作业整体的负载均衡保持得比较好。

reduce输出的数据存储在hdfs中,可以通过文件夹的名称来引用。若文件夹作为一个作业的输入,那么该文件夹下的所有文件都会被处理。上文介绍的get和copytolocal只能对文件进行复制,无法对整个文件夹进行复制2。当然hadoop提供了getmerge命令,可以将文件系统中的多个文件合并成一个单独的文件下载到本地文件系统。

通过以下pig脚本来演示下getmerge命令的功能:

pig脚本可以通过下面的命令行来执行:

《Hadoop实战手册》一1.2 使用Hadoop shell命令导入和导出数据到HDFS

该脚本逐行读取hdfs上的weblog_entries.txt文件,并且按照md5的值进行分组。parallel是pig脚本用来设置reduce个数的方法。由于启动了4个reduce任务,所以会在输出的目录/data/weblogs/weblogs_md5_groups.bcp中生成4个文件。

注意,weblogs_md5_groups.bcp实际上是一个文件夹,显示该文件夹的列表信息可以看到:

《Hadoop实战手册》一1.2 使用Hadoop shell命令导入和导出数据到HDFS

在/data/weblogs/weblogs_md5_groups.bcp中包含4个文件,即part-r-00000、part-r-00001、part-r-00002和part-r-00003。

getmerge命令可以用来将4个文件合并成一个文件,并且复制到本地的文件系统中,具体命令如下:

操作完我们可以看到本地文件列表如下:

《Hadoop实战手册》一1.2 使用Hadoop shell命令导入和导出数据到HDFS

延伸阅读

u关于hdfs数据的读写,我们将在第2章中重点介绍如何直接利用文件系统的api进行读写。

通过以下的两个链接可以对比出文件系统shell命令与java api的不同:

继续阅读