Hadoop教程

通过distcp并行复制

前面着重介绍单线程访问的HDFS访问模型。例如,通过指定文件通配符,可以对一组文件进行处理,但是为了提高性能,需要写一个程序来并行处理这些文件。 Hadoop有一个有用的distcp分布式复制程序,该程序可以从Hadoop文件系统中复制大量的数据,也可以将大量的数据复制到Hadoop中。

distcp的典型应用是在两个HDFS集群之间传输数据。如果两个集群运行相同版本的Hadoop,就非常适合使用hdfs方案:

    % hadoop distcp hdfs://namenodel/foo hdfs://namenode2/bar

这行指令将把第一个集群/foo目录(和它的内容)复制到第二个集群的/bar目录下, 所以第二个集群最后拥有目录结构/bar//f00。如果/bar不存在,则新建一个。你也可以指定多个源路径,并把所有的路径都复制到目标路径下。注意,源路径必须是绝对路径。

默认情况下,distcp会跳过目标路径下已经存在的文件,但可以通过overwrite选项覆盖现有的文件。也可以通过-update选项来选择仅更新修改过的文件。

    % hadoop distcp -update hdfs://namenodel/foo hdfs://namenode2/bar/foo

因为源目录下的内容已被复制到目标目录下,所以需要在目标路径中添加额外的子目录/foo(如果对rsync命令比较熟悉,可以认为 -overwrite 或-update选项就是在源路径末尾添加一个斜杠。)

如果不确定discp操作的效果,最好先在一个小的测试目录树下试着运行一次。

有很多选项可以控制distcp的复制方式,包括保留文件属性,忽略故障和限制复制文件或总数据的数量。不带任何选项运行时,将显示使用说明。

distcp是作为一个MapReduce作业来实现的,该复制作业是通过集群中并行运行的map来完成。这里没有reducer,毎个文件通过单一的map进行复制,并且distcp 试图为毎一个map分配大致相等的数据来执行,这一步通过将文件划分为大致相等的块来实现。

map的数量是这样确定的。让每一个map复制合理的数据量来尽量减少构建任务时所涉及的开销,这是一个很好的想法,所以每个map至少复制256 MB数据 (除非输入的总数据量较少,否则一个map就可以完成所有的复制)。例如,将1 GB大小的文件分给4个map任务。如果数据非常大,则有必要限制map的数量进而限制带宽和集群的使用。默认情况下,每个集群节点(或tasktracker)最多分配20个map任务。例如,将1000GB的文件复制到一个由100个节点组成的集群, 一共分配2000个map任务(每个节点20个map任务),所以每个map任务平均复 制512 MB数据。通过对distcp 指定-m参数,可以减少分配的map任务数。例如,-m1000将分配1000个map)任务,每个平均复制1GB数据。

如果试图在两个运行着不同HDFS版本的集群上使用distcp复制数据,并且使用hdfs协议,会导致复制作业失败,因为两个版本的RPC系统是不兼容的。想要弥补这种情况,可以使用基于只读HTTP协议的HFTP文件系统并从源文件系统中读取数据。这个作业必须运行在目标集群上,进而实现HDFS RPC版本的兼容。使用HFTP协议重复前面的例子:

% hadoop distcp hftp://namenodel:50070/foo hdfs://namenode2/bar

注意,需要在URI源中指定namenode的Web端口。这是由dfs.http.address 属性决定的,其默认值为50070。

保持HDFS集群的均衡

向HDFS复制数据时,考虑集群的平衡性是相当重要的。当文件块在集群中均匀地分布时,HDFS能达到最佳工作状态。回到前面1000GB数据的例子,将-m选项指定为1,即由一个1个map来执行复制作业,它的意思是———不考虑速度变慢和未充分利用集群资源———每个块的第一个复本将存储到运行map的节点上(直到磁盘被填满)。第二和第三个复本将分散在集群中,但这一个节点是不平衡的。将map 的数量设定为多于集群中节点的数量,可以避免这个问题———鉴于此,最好首先使用默认的每个节点20个map来运行distcp命令。

然而,这也并不总能阻止集群的不平衡。也许想限制map的数量以便另外一些节点可用于其他作业。若是这样,可以使用均衡器(balancer)这个平衡工具进而改善集群中块分布的均匀程度。

关注微信获取最新动态