Hadoop HDFS原理

来源:互联网 发布:电影软件 比价 编辑:程序博客网 时间:2024/06/09 21:36

1 HDFS的运行机制

HDFS集群中的节点分为两种角色,一种角色负责管理整个集群的元数据,是名称节点(name node);另一种角色负责存储文件数据块和管理文件数据块,是数据节点(datanode)。

1.1 NameNode

      1.1.1名称节点负责响应客户端的请求,负责管理整个文件系统的元数据。

       1.1.2HDFS的内部工作机制对客户端是透明的,客户端对HDFS的读、写操作都必须先向name node申请。所以元数据是关键。

       1.1.3负责维持文件的副本数量

       1.1.4 为了保证集群的元数据不丢失,生产环境下需要配置辅助名称节点(secondary name node,简称2NN)作为元数据的备份,万一name node的元数据丢失就可以从2NN恢复元数据。

       1.1.5 名称节点可用的前提是此节点运行名为“NameNode”的进程。

 

1.2 数据节点Data Node

1.2.1 负责存放被切割后的文件块。文件在data node的存储单位是块(block)。

1.2.2 如果hadoop集群是完全分布式模式,那么一个文件的每一个块必须有多个副本,存放在不同的datanode上。当客户端把某个文件写入HDFS时,首先按照固定的块大小(block size)把该文件切成若干个块,再分布式地存储在若干台data node上。

1.2.3 data node通过心跳信息定期地向name node汇报自身保存的文件块信息。

1.2.4 数据节点可用的前提是此节点运行名为“DataNode”的进程。

 

下面介绍一下客户端向HDFS写数据和读数据的流程,hadoop集群规模以“1台namenode + 3台data node”为例。

1.3 客户端向HDFS写数据的流程

1.3.1 客户端和name node通信,name node检查目标文件是否已存在,父目录是否存在,检查通过以后name node通知客户端可以写入

1.3.2 客户端向name node请求上传文件的第一个块(block1),询问name node应该把block1上传到哪些data node主机上。客户端每传一个block都要向name node请求

1.3.3 name node把3台data node服务器信息返回给客户端。基于可靠性的考虑,每个文件块都有副本,每个副本分别存放在不同的data node服务器上。副本存放的data node选择策略:首选在本地机架的一个节点上存放副本, 第二个副本在本地机架的另一个不同节点,第三个副本在不同机架的不同节点上

1.3.4 正式上传之前,客户端请求与3台中的其中一台(dn1)建立传输通道,dn1又和dn2主机建立传输通道,dn2又和dn3建立传输通道

1.3.5整个传输通道建立完成后,客户端把block1从磁盘读出来放到本地缓存, 开始向dn1上传block1,上传时以package为单位进行传输,package默认大小64kb。dn1每收到一个package就会复制一份传给dn2,dn2再复制一份传给dn3。

1.3.6 当block1传输完成后,客户端再次向name node申请上传此文件的第二个块block2

 

1.4 客户端从HDFS读数据的流程

1.4.1 客户端和name node通信,查询元数据,找到文件块存放的data node服务器信息

1.4.2 客户端收到name node返回的信息(例如block1存放在dn1和dn2上,block2在dn2和dn3上),去找到相应的dn(按就近挑选dn原则,然后随机),再请求和dn建立socket流

1.4.3 socket流建立好以后,dn开始向客户端发送数据(从磁盘读取数据放入socket流)

1.4.4 客户端以packet为单位接收文件块,把各个块在本地合并成一个完整的文件

 

1.5 名称节点是如何管理元数据的?

Name node对数据的管理采用了三种存储形式:memory meta data, fsimage, edit log.

1.5.1 memorymeta data:内存元数据。在name node服务器启动时会把fsimage从磁盘加载到内存,有了元数据就可以向客户端提供读、写服务了

1.5.2 fsimage是在磁盘中的元数据镜像文件,整个文件系统的元数据(包括所有目录和文件inode序列化信息)都永久保存在此文件里;它位于name node的工作目录中

1.5.3 edit logs是数据操作日志文件(可通过日志运算出元数据),客户端对HDFS中的文件进行写操作(增加或删除)之前,先把此操作行为记录到edit log文件中,再把成功操作代码发送给客户端。edit log需要定期通过checkpoint机制融合到fsimage,以保证name node的元数据是最新的,详见下面的描述。

 

1.6 若名称节点发生磁盘故障,如何挽救集群以及数据?

这个需要提前单独准备一台主机,专门用于部署辅助名称节点(2NN)。同时,name node(NN)和2NN的工作目录存储结构完全相同,这样一来,一旦NN服务器挂掉,可以从2NN的工作目录中将fsimage拷贝到NN的工作目录,以恢复元数据。注意:这种补救措施是事后的,不能保证内存中的元数据是最新的,因为2NN不能充当name node使用(只有name node才能及时更新元数据)。要想让HDFS集群持续对外提供服务,需要引入高可用(HA)配置,HDFS高可用的原理可继续阅读下文。

实际上2NN是用来备份NN中的元数据,备份的内容包括NN服务器上最新的fsimage文件以及全部的日志文件(edit log),备份的过程叫做checkpoint(检查点),过程概要:每隔一段时间,会由2NN将NN上积累的所有edits和一个最新的fsimage下载到2NN本地,并加载到内存进行merge(融合),再把融合后的文件上传给NN。具体checkpoint流程如下:

1.6.1 在做检查点之前,先让NN上正在写的日志文件滚动一下,以供2NN拷贝。日志文件和fsimage的路径可从配置文件hdfs-site.xml的dfs.namenode.name.dir属性中找到,例如我的元数据存放的路径是/home/centos/namemeta

       <property>

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

              <value>/home/centos/namemeta</value>

       </property>

下面有个子目录current存放所有的fsimage和edit log文件,查看此目录的树结构:

current/
|-- edits_0000000000000010612-0000000000000010613
|-- edits_0000000000000010614-0000000000000010615
|-- edits_0000000000000010616-0000000000000010617
|-- edits_inprogress_0000000000000010618
|-- fsimage_0000000000000010472
|-- fsimage_0000000000000010472.md5
|-- fsimage_0000000000000010563
|-- fsimage_0000000000000010563.md5
`-- seen_txid

1.6.2 在HDFS集群首次做检查点时才会从NN下载最新的fsimage文件,以后做检查点时只需下载NN上的edit log(因为editlog比fsimage要小)。2NN有了fsimage和editlog,就可以在2NN服务器的内存中对二者进行融合,生成一个检查点文件fsimage.checkpoint,再把此文件上传到NN并重命名为fsimage文件

1.6.3 NN根据刚才2NN传来的最新fsimage更新内存中的元数据

1.6.4 默认是间隔30分钟做一次checkpoint

 

 

2 如何实现HDFS高可用

HDFS的高可用指的是HDFS持续对各类客户端提供读、写服务的能力,因为客户端对HDFS的读、写操作之前都要访问name node服务器,客户端只有从name node获取元数据之后才能继续进行读、写。所以HDFS的高可用的关键在于name node上的元数据持续可用。

前面说过2NN的功能是checkpoint,把NN的fsimage和edit log做定期融合,融合后传给NN, 以确保备份到的元数据是最新的,这一点类似于做了一个元数据的快照。Hadoop官方提供了一种quorum journal manager来实现高可用,那么就没必要配置2NN了。

在高可用配置下,edit log不再存放在名称节点,而是存放在一个共享存储的地方,这个共享存储由若干个Journal Node组成,一般是3个节点(JN小集群), 每个JN专门用于存放来自NN的编辑日志,编辑日志由活跃状态的名称节点写入。

要有2个名称节点,二者之中只能有一个处于活跃状态(active),另一个是待命状态(standby),只有active节点才能对外提供读写HDFS服务,也只有active态的NN才能向JN写入编辑日志;standby的名称节点只负责从JN小集群中的JN节点拷贝数据到本地存放。另外,各个DATA NODE也要同时向两个名称节点报告状态(心跳信息、块信息)。

       那么一主一从的2个名称节点同时和3个JN构成的组保持通信,活跃的名称节点负责往JN集群写入编辑日志,待命的名称节点负责观察JN组中的编辑日志,并且把日志拉取到待命节点。再加上俩节点各自的fsimage镜像文件,这样一来就能确保两个NN的元数据保持同步。一旦active不可用,提前配置的zookeeper会把standby节点自动变为active,继续对外提供服务。详见下文的 2.2如何通过自动容灾而不是手动容灾?

 

2.1手动实现高可用的大概流程:

2.1.1 准备3台服务器分别用于运行JournalNode进程(也可以运行在date node服务器上),准备2台namenode服务器用于运行NameNode进程,数据节点数量不限

2.1.2 分别启动3台JN服务器上的JournalNode进程,分别在date node服务器启动DataNode进程

2.1.3 需要同步2台name node之间的元数据。具体做法:从第一台NN拷贝元数据到放到另一台NN,然后启动第一台的NameNode进程,再到另一台名称节点上做standby引导

2.1.4 把第一台名节点的edit日志初始化到JN节点,以供standby节点到JN节点拉取数据

2.1.5启动standby状态的名称节点,这样就能同步fsimage文件

2.1.6 模拟故障,手动把active状态的NN故障,转移到另一台NN


 

2.2如何通过自动容灾而不是手动容灾?

通过zookeeper实现。

自动容灾引入两个组件:zk quarum + zk容灾控制器。

运行NN的2台主机还要运行ZKFC进程(DFSZKFailoverController),主要负责: 健康监控、session管理、leader选举。

大概流程是:

2.2.7 在上面HA配置的基础上,要另外准备3台主机安装zookeeper,3台主机形成一个小的zk集群.

2.2.8 启动ZK集群每个节点上的QuorumPeerMain进程

2.2.9 登录其中一台NN, 在ZK中初始化HA状态

2.2.10 模拟故障:停掉活跃的NameNode进程,会发现自动切换active到另一台NN,模拟过程如下——

 

[centos@h201 current]$ xcall jps             # 查看HDFS集群的每个节点上运行哪些进程

----------执行jps 在主机h201

44992 DFSZKFailoverController

46624 Jps

44110 QuorumPeerMain

44686 NameNode

命令已成功执行!----------

 

----------执行jps 在主机h202

17521 Jps

17210 DataNode

17021 QuorumPeerMain

17310 JournalNode

命令已成功执行!----------

 

----------执行jps 在主机h203

15777 JournalNode

15988 Jps

15494 QuorumPeerMain

15677 DataNode

命令已成功执行!----------

 

----------执行jps 在主机h204

16516 DataNode

16616 JournalNode

16826 Jps

命令已成功执行!----------

 

----------执行jps 在主机h205

23170 DFSZKFailoverController

23844 Jps

23064 NameNode

命令已成功执行!----------

 

[centos@h201 hadoop]$ hdfs haadmin-getServiceState nn1          #h201是第一台NN

active

[centos@h201 hadoop]$ hdfs haadmin-getServiceState nn2          # h205是另一台NN

standby

[centos@h201 hadoop]$jps

44992 DFSZKFailoverController

44110 QuorumPeerMain

44686 NameNode

47326 Jps

[centos@h201 hadoop]$kill -9 44686         # 模拟nn1故障, DFSZKFailoverController自动把nn2激活

[centos@h201 hadoop]$ hdfs haadmin-getServiceState nn2

active


1 环境说明

部署节点操作系统为CentOS,防火墙和SElinux禁用,创建了一个shiyanlou用户并在系统根目录下创建/app目录,用于存放 Hadoop等组件运行包。因为该目录用于安装hadoop等组件程序,用户对shiyanlou必须赋予rwx权限(一般做法是root用户在根目录下 创建/app目录,并修改该目录拥有者为shiyanlou(chown –R shiyanlou:shiyanlou /app)。

Hadoop搭建环境:

  • 虚拟机操作系统: CentOS6.6 64位,单核,1G内存
  • JDK:1.7.0_55 64位
  • Hadoop:1.1.2

2 HDFS原理

HDFS(Hadoop Distributed File System)是一个分布式文件系统,是谷歌的GFS山寨版本。它具有高容错性并提供了高吞吐量的数据访问,非常适合大规模数据集上的应用,它提供了一个高度容错性和高吞吐量的海量数据存储解决方案。

  • 高吞吐量访问:HDFS的每个Block分布在不同的Rack上,在用户访问时,HDFS会计算使用最近和访问量最小的服务器给用户提供。由于 Block在不同的Rack上都有备份,所以不再是单数据访问,所以速度和效率是非常快的。另外HDFS可以并行从服务器集群中读写,增加了文件读写的访 问带宽。
  • 高容错性:系统故障是不可避免的,如何做到故障之后的数据恢复和容错处理是至关重要的。HDFS通过多方面保证数据的可靠性,多份复制并且分布到物理位置的不同服务器上,数据校验功能、后台的连续自检数据一致性功能都为高容错提供了可能。
  • 线性扩展:因为HDFS的Block信息存放到NameNode上,文件的Block分布到DataNode上,当扩充的时候仅仅添加DataNode数量,系统可以在不停止服务的情况下做扩充,不需要人工干预。

2.1 HDFS架构

如上图所示HDFS是Master和Slave的结构,分为NameNode、Secondary NameNode和DataNode三种角色。

  • NameNode:在Hadoop1.X中只有一个Master节点,管理HDFS的名称空间和数据块映射信息、配置副本策略和处理客户端请求;
  • Secondary NameNode:辅助NameNode,分担NameNode工作,定期合并fsimage和fsedits并推送给NameNode,紧急情况下可辅助恢复NameNode;
  • DataNode:Slave节点,实际存储数据、执行数据块的读写并汇报存储信息给NameNode;

2.2 HDFS读操作

  1. 客户端通过调用FileSystem对象的open()方法来打开希望读取的文件,对于HDFS来说,这个对象时分布文件系统的一个实例;
  2. DistributedFileSystem通过使用RPC来调用NameNode以确定文件起始块的位置,同一Block按照重复数会返回多个位置,这些位置按照Hadoop集群拓扑结构排序,距离客户端近的排在前面;
  3. 前两步会返回一个FSDataInputStream对象,该对象会被封装成DFSInputStream对象,DFSInputStream可以方便的管理datanode和namenode数据流,客户端对这个输入流调用read()方法;
  4. 存储着文件起始块的DataNode地址的DFSInputStream随即连接距离最近的DataNode,通过对数据流反复调用read()方法,可以将数据从DataNode传输到客户端;
  5. 到达块的末端时,DFSInputStream会关闭与该DataNode的连接,然后寻找下一个块的最佳DataNode,这些操作对客户端来说是透明的,客户端的角度看来只是读一个持续不断的流;
  6. 一旦客户端完成读取,就对FSDataInputStream调用close()方法关闭文件读取。

2.3 HDFS写操作

  1. 客户端通过调用DistributedFileSystem的create()方法创建新文件;
  2. DistributedFileSystem通过RPC调用NameNode去创建一个没有Blocks关联的新文件,创建前NameNode会 做各种校验,比如文件是否存在、客户端有无权限去创建等。如果校验通过,NameNode会为创建新文件记录一条记录,否则就会抛出IO异常;
  3. 前两步结束后会返回FSDataOutputStream的对象,和读文件的时候相似,FSDataOutputStream被封装成 DFSOutputStream,DFSOutputStream可以协调NameNode和Datanode。客户端开始写数据到 DFSOutputStream,DFSOutputStream会把数据切成一个个小的数据包,并写入内部队列称为“数据队列”(Data Queue);
  4. DataStreamer会去处理接受Data Queue,它先问询NameNode这个新的Block最适合存储的在哪几个DataNode里,比如重复数是3,那么就找到3个最适合的 DataNode,把他们排成一个pipeline.DataStreamer把Packet按队列输出到管道的第一个Datanode中,第一个 DataNode又把Packet输出到第二个DataNode中,以此类推;
  5. DFSOutputStream还有一个对列叫Ack Quene,也是有Packet组成,等待DataNode的收到响应,当Pipeline中的所有DataNode都表示已经收到的时候,这时Akc Quene才会把对应的Packet包移除掉;
  6. 客户端完成写数据后调用close()方法关闭写入流;
  7. DataStreamer把剩余的包都刷到Pipeline里然后等待Ack信息,收到最后一个Ack后,通知NameNode把文件标示为已完成。

2.4 HDFS中常用到的命令

1. hadoop fs

  • hadoop fs -ls /
  • hadoop fs -lsr
  • hadoop fs -mkdir /user/hadoop
  • hadoop fs -put a.txt /user/hadoop/
  • hadoop fs -get /user/hadoop/a.txt /
  • hadoop fs -cp src dst
  • hadoop fs -mv src dst
  • hadoop fs -cat /user/hadoop/a.txt
  • hadoop fs -rm /user/hadoop/a.txt
  • hadoop fs -rmr /user/hadoop/a.txt
  • hadoop fs -text /user/hadoop/a.txt
  • hadoop fs -copyFromLocal localsrc dst 与hadoop fs -put功能类似。
  • hadoop fs -moveFromLocal localsrc dst 将本地文件上传到hdfs,同时删除本地文件。

2. hadoop fsadmin

  • hadoop dfsadmin -report
  • hadoop dfsadmin -safemode enter | leave | get | wait
  • hadoop dfsadmin -setBalancerBandwidth 1000

3. hadoop fsck

4. start-balancer.sh

相关HDFS API可以到Apache官网进行查看: 

3 测试例子1

3.1 测试例子1内容

在Hadoop集群中编译并运行《权威指南》中的例3.2,读取HDFS文件内容。

3.2 运行代码

import java.io.InputStream;import java.net.URI;import org.apache.hadoop.conf.Configuration;import org.apache.hadoop.fs.*;import org.apache.hadoop.io.IOUtils;public class FileSystemCat {    public static void main(String[] args) throws Exception {        String uri = args[0];        Configuration conf = new Configuration();        FileSystem fs = FileSystem. get(URI.create (uri), conf);        InputStream in = null;    try {            in = fs.open( new Path(uri));            IOUtils.copyBytes(in, System.out, 4096, false);        } finally {            IOUtils.closeStream(in);        }    }}

3.3 实现过程

3.3.1 创建代码目录

配置本机主机名为hadoop,sudo时需要输入shiyanlou用户的密码:shiyanlou。将hadoop添加到第一行的最后。

sudo vim /etc/hosts# 将hadoop添加到第一行末尾,修改后类似:# 172.17.2.98 f738b9456777 hadoopping hadoop

使用如下命令启动Hadoop

cd /app/hadoop-1.1.2/bin./start-all.sh

在/app/hadoop-1.1.2目录下使用如下命令建立myclass和input目录:

cd /app/hadoop-1.1.2rm -rf myclassrm -rf inputmkdir myclassmkdir input

3.3.2 建立例子文件上传到HDFS中

进入/app/hadoop-1.1.2/input目录,在该目录中建立quangle.txt文件

cd /app/hadoop-1.1.2/inputtouch quangle.txtvi quangle.txt

内容为:

On the top of the Crumpetty TreeThe Quangle Wangle sat,But his face you could not see,On account of his Beaver Hat.

使用如下命令在hdfs中建立目录/class4

  • hadoop fs -mkdir /class4
  • hadoop fs -ls /

(如果需要直接使用hadoop命令,需要把/app/hadoop-1.1.2加入到Path路径中) 

把例子文件上传到hdfs的/class4文件夹中

  • cd /app/hadoop-1.1.2/input
  • hadoop fs -copyFromLocal quangle.txt /class4/quangle.txt
  • hadoop fs -ls /class4

3.3.3 配置本地环境

对/app/hadoop-1.1.2/conf目录中的hadoop-env.sh进行配置,如下如所示:

  • cd /app/hadoop-1.1.2/conf
  • sudo vi hadoop-env.sh

加入对HADOOP_CLASPATH变量值,值为/app/hadoop-1.1.2/myclass,设置完毕后编译该配置文件,使配置生效

  • export HADOOP_CLASSPATH=/app/hadoop-1.1.2/myclass

3.3.4 编写代码

进入/app/hadoop-1.1.2/myclass目录,在该目录中建立FileSystemCat.java代码文件,命令如下:

  • cd /app/hadoop-1.1.2/myclass/
  • vi FileSystemCat.java

输入代码内容:

3.3.5 编译代码

在/app/hadoop-1.1.2/myclass目录中,使用如下命令编译代码:

  • javac -classpath ../hadoop-core-1.1.2.jar FileSystemCat.java

3.3.6 使用编译代码读取HDFS文件

使用如下命令读取HDFS中/class4/quangle.txt内容:

  • hadoop FileSystemCat /class4/quangle.txt

4 测试例子2

4.1 测试例子2内容

在本地文件系统生成一个大约100字节的文本文件,写一段程序读入这个文件并将其第101-120字节的内容写入HDFS成为一个新文件。

4.2 运行代码

注意:在编译前请先删除中文注释!import java.io.File;import java.io.FileInputStream;import java.io.FileOutputStream;import java.io.OutputStream;import java.net.URI;import org.apache.hadoop.conf.Configuration;import org.apache.hadoop.fs.FSDataInputStream;import org.apache.hadoop.fs.FileSystem;import org.apache.hadoop.fs.Path;import org.apache.hadoop.io.IOUtils;import org.apache.hadoop.util.Progressable;public class LocalFile2Hdfs {    public static void main(String[] args) throws Exception {        // 获取读取源文件和目标文件位置参数        String local = args[0];        String uri = args[1];        FileInputStream in = null;        OutputStream out = null;        Configuration conf = new Configuration();        try {            // 获取读入文件数据            in = new FileInputStream(new File(local));            // 获取目标文件信息            FileSystem fs = FileSystem.get(URI.create(uri), conf);            out = fs.create(new Path(uri), new Progressable() {                @Overridepublic void progress() {                    System.out.println("*");                }            });            // 跳过前100个字符            in.skip(100);            byte[] buffer = new byte[20];            // 从101的位置读取20个字符到buffer中int bytesRead = in.read(buffer);            if (bytesRead >= 0) {                out.write(buffer, 0, bytesRead);            }        } finally {            IOUtils.closeStream(in);            IOUtils.closeStream(out);        }            }}

4.3 实现过程

4.3.1 编写代码

进入/app/hadoop-1.1.2/myclass目录,在该目录中建立LocalFile2Hdfs.java代码文件,命令如下:

  • cd /app/hadoop-1.1.2/myclass/
  • vi LocalFile2Hdfs.java

输入代码内容:

4.3.2 编译代码

在/app/hadoop-1.1.2/myclass目录中,使用如下命令编译代码:

  • javac -classpath ../hadoop-core-1.1.2.jar LocalFile2Hdfs.java

4.3.3 建立测试文件

进入/app/hadoop-1.1.2/input目录,在该目录中建立local2hdfs.txt文件

  • cd /app/hadoop-1.1.2/input/
  • vi local2hdfs.txt

内容为:

Washington (CNN) -- Twitter is suing the U.S. government in an effort to loosen restrictions on what the social media giant can say publicly about the national security-related requests it receives for user data.The company filed a lawsuit against the Justice Department on Monday in a federal court in northern California, arguing that its First Amendment rights are being violated by restrictions that forbid the disclosure of how many national security letters and Foreign Intelligence Surveillance Act court orders it receives -- even if that number is zero.Twitter vice president Ben Lee wrote in a blog post that it's suing in an effort to publish the full version of a "transparency report" prepared this year that includes those details.The San Francisco-based firm was unsatisfied with the Justice Department's move in January to allow technological firms to disclose the number of national security-related requests they receive in broad ranges.

4.3.4 使用编译代码上传文件内容到HDFS

使用如下命令读取local2hdfs第101-120字节的内容写入HDFS成为一个新文件:

  • cd /app/hadoop-1.1.2/input
  • hadoop LocalFile2Hdfs local2hdfs.txt /class4/local2hdfs_part.txt

4.3.5 验证是否成功

使用如下命令读取local2hdfs_part.txt内容:

  • hadoop fs -cat /class4/local2hdfs_part.txt

5 测试例子3

5.1 测试例子3内容

测试例子2的反向操作,在HDFS中生成一个大约100字节的文本文件,写一段程序读入这个文件,并将其第101-120字节的内容写入本地文件系统成为一个新文件。

5.2 程序代码

import java.io.File;import java.io.FileInputStream;import java.io.FileOutputStream;import java.io.OutputStream;import java.net.URI;import org.apache.hadoop.conf.Configuration;import org.apache.hadoop.fs.FSDataInputStream;import org.apache.hadoop.fs.FileSystem;import org.apache.hadoop.fs.Path;import org.apache.hadoop.io.IOUtils;public class Hdfs2LocalFile {    public static void main(String[] args) throws Exception {        String uri = args[0];        String local = args[1];        FSDataInputStream in = null;        OutputStream out = null;        Configuration conf = new Configuration();        try {            FileSystem fs = FileSystem.get(URI.create(uri), conf);            in = fs.open(new Path(uri));            out = new FileOutputStream(local);            byte[] buffer = new byte[20];            in.skip(100);            int bytesRead = in.read(buffer);            if (bytesRead >= 0) {                out.write(buffer, 0, bytesRead);            }        } finally {            IOUtils.closeStream(in);            IOUtils.closeStream(out);        }        }}

5.3 实现过程

5.3.1 编写代码

进入/app/hadoop-1.1.2/myclass目录,在该目录中建立Hdfs2LocalFile.java代码文件,命令如下:

  • cd /app/hadoop-1.1.2/myclass/
  • vi Hdfs2LocalFile.java

输入代码内容:

5.3.2 编译代码

在/app/hadoop-1.1.2/myclass目录中,使用如下命令编译代码:

  • javac -classpath ../hadoop-core-1.1.2.jar Hdfs2LocalFile.java

5.3.3 建立测试文件

进入/app/hadoop-1.1.2/input目录,在该目录中建立hdfs2local.txt文件

  • cd /app/hadoop-1.1.2/input/
  • vi hdfs2local.txt

内容为:

The San Francisco-based firm was unsatisfied with the Justice Department's move in January to allow technological firms to disclose the number of national security-related requests they receive in broad ranges."It's our belief that we are entitled under the First Amendment to respond to our users' concerns and to the statements of U.S. government officials by providing information about the scope of U.S. government surveillance -- including what types of legal process have not been received," Lee wrote. "We should be free to do this in a meaningful way, rather than in broad, inexact ranges."

在/app/hadoop-1.1.2/input目录下把该文件上传到hdfs的/class4/文件夹中

  • hadoop fs -copyFromLocal hdfs2local.txt /class4/hdfs2local.txt
  • hadoop fs -ls /class4/

5.3.4 使用编译代码把文件内容从HDFS输出到文件系统中

使用如下命令读取hdfs2local.txt第101-120字节的内容写入本地文件系统成为一个新文件:

  • hadoop Hdfs2LocalFile /class4/hdfs2local.txt hdfs2local_part.txt

5.3.5 验证是否成功

使用如下命令读取hdfs2local_part.txt内容:

  • cat hdfs2local_part.txt


原创粉丝点击