第三章 分布式文件系统HDFS
分布式文件系统
计算机集群结构
1 | •分布式文件系统把文件分布存储到多个计算机节点上,成千上万的计算机节点构成计算机集群 |

分布式文件系统的结构
1 | 分布式文件系统在物理结构上是由计算机集群中的多个节点构成的,这些节点分为两类,一类叫“主节点”(Master Node)或者也被称为“名称结点”(NameNode),另一类叫“从节点”(Slave Node)或者也被称为“数据节点”(DataNode) |

HDFS简介
1 | 总体而言,HDFS要实现以下目标: |
HDFS相关概念
块
1 | HDFS默认一个块64MB,一个文件被分成多个块,以块作为存储单位块的大小远远大于普通文件系统,可以最小化寻址开销 |
名称节点和数据节点

名称节点的数据结构
1 | •在HDFS中,名称节点(NameNode)负责管理分布式文件系统的命名空间(Namespace),保存了两个核心的数据结构,即FsImage和EditLog |

FsImage文件
1 | •FsImage文件包含文件系统中所有目录和文件inode的序列化形式。每个inode是一个文件或目录的元数据的内部表示,并包含此类信息:文件的复制等级、修改和访问时间、访问权限、块大小以及组成文件的块。对于目录,则存储修改时间、权限和配额元数据 |
名称节点的启动
1 | •在名称节点启动的时候,它会将FsImage文件中的内容加载到内存中,之后再执行EditLog文件中的各项操作,使得内存中的元数据和实际的同步,存在内存中的元数据支持客户端的读操作。 |
名称节点运行期间EditLog不断变大的问题
1 | •在名称节点运行期间,HDFS的所有更新操作都是直接写到EditLog中,久而久之, EditLog文件将会变得很大 |
第二名称节点SecondaryNameNode
1 | 第二名称节点是HDFS架构中的一个组成部分,它是用来保存名称节点中对HDFS |
1 | SecondaryNameNode的工作情况: |
数据节点DataNode
1 | •数据节点是分布式文件系统HDFS的工作节点,负责数据的存储和读取,会根据客户端或者是名称节点的调度来进行数据的存储和检索,并且向名称节点定期发送自己所存储的块的列表 |
HDFS体系结构
HDFS体系结构概述
1 | HDFS采用了主从(Master/Slave)结构模型,一个HDFS集群包括一个名称节点(NameNode)和若干个数据节点(DataNode)(如图3-4所示)。名称节点作为中心服务器,负责管理文件系统的命名空间及客户端对文件的访问。 |
HDFS命名空间管理
1 | • HDFS的命名空间包含目录、文件和块 |
通信协议
1 | • HDFS是一个部署在集群上的分布式文件系统,因此,很多数据需要 |
客户端
1 | • 客户端是用户操作HDFS最常用的方式,HDFS在部署时都提供了客户端 |
HDFS体系结构的局限性
1 | HDFS只设置唯一一个名称节点,这样做虽然大大简化了系统设计,但也带来了一些明显的局限性,具体如下: |
HDFS存储原理
冗余数据保存
1 | 作为一个分布式文件系统,为了保证系统的容错性和可用性,HDFS采用了多副本方式对数据进行冗余存储,通常一个数据块的多个副本会被分布到不同的数据节点上,如图3-5所示,数据块1被分别存放到数据节点A和C上,数据块2被存放在数据节点A和B上。这种多副本方式具有以下几个优点: |
数据存取策略
数据存放
1 | •第一个副本:放置在上传文件的数据节点;如果是集群外提交,则随机挑选一台磁盘不太满、CPU不太忙的节点 |
数据读取
1 | •HDFS提供了一个API可以确定一个数据节点所属的机架ID,客户端也可以调用API获取自己所属的机架ID |
数据错误与恢复
1 | HDFS具有较高的容错性,可以兼容廉价的硬件,它把硬件出错看作一种常态,而不是异常,并设计了相应的机制检测数据错误和进 |
名称节点出错
1 | 名称节点保存了所有的元数据信息,其中,最核心的两大数据 |
数据节点出错
1 | •每个数据节点会定期向名称节点发送“心跳”信息,向名称节点报告自己的状态 |
数据出错
1 | •网络传输和磁盘错误等因素,都会造成数据错误 |
HDFS数据读写过程
1 | 是hdfs中比较核心的东西 |
读取文件

1 | import java.io.BufferedReader; |
写入文件
1 | import org.apache.hadoop.conf.Configuration; |
1 | •FileSystem是一个通用文件系统的抽象基类,可以被分布式文件系统继承,所有可能使用Hadoop文件系统的代码,都要使用这个类 |
1 | Configuration conf = new Configuration(); |
1 | 备注:创建一个Configuration对象时,其构造方法会默认加载工程项目下两个配置文件,分别是hdfs-site.xml以及core-site.xml,这两个文件中会有访问HDFS所需的参数值,主要是fs.defaultFS,指定了HDFS的地址(比如hdfs://localhost:9000),有了这个地址客户端就可以通过这个地址访问HDFS了 |
HDFS编程实践
[分布式文件系统HDFS 学习指南](大数据技术原理与应用 第三章 分布式文件系统HDFS 学习指南_厦大数据库实验室博客 (xmu.edu.cn))
HDFS常用命令
1 | 备注:Hadoop中有三种Shell命令方式: |
1 | hadoop fs -ls <path>:显示<path>指定的文件的详细信息 |

1 | hadoop fs -cat <path>:将<path>指定的文件的内容输出到标准输出(stdout) |

目录操作
1 | ./bin/hadoop fs 查看fs总共支持了哪些命令 |
文件操作
1 | ./bin/hdfs dfs -put /home/hadoop/myLocalFile.txt input |
1 | ./bin/hdfs dfs –cat input/myLocalFile.txt |
1 | ./bin/hdfs dfs -get input/myLocalFile.txt /home/hadoop/下载 |
1 | ./bin/hdfs dfs -cp input/myLocalFile.txt /input |
HDFS的Web界面
1 | 在配置好Hadoop集群之后,可以通过浏览器登录 |
HDFS常用Java API及应用实例
1 | 利用Java API与HDFS进行交互 |
1 | 下面提供了Hadoop官方的Hadoop API文档,想要深入学习Hadoop,可以访问如下网站,查看各个API的功能。 |
在Eclipse创建项目
1 | 在“Project name”后面输入工程名称“HDFSExample”,选中“Use default location”,让这个Java工程的所有文件都保存到“/home/hadoop/workspace/HDFSExample”目录下。在“JRE”这个选项卡中,可以选择当前的Linux系统中已经安装好的JDK,比如java-8-openjdk-amd64。然后,点击界面底部的“Next>”按钮,进入下一步的设置。 |
为项目添加需要用到的JAR包
1 | 进入下一步的设置以后,会弹出如图4-5所示界面。 |
1 | 需要在这个界面中加载该Java工程所需要用到的JAR包,这些JAR包中包含了可以访问HDFS的Java API。这些JAR包都位于Linux系统的Hadoop安装目录下,对于本教程而言,就是在“/usr/local/hadoop/share/hadoop”目录下。点击界面中的“Libraries”选项卡,然后,点击界面右侧的“Add External JARs…”按钮,会弹出如图4-6所示界面。 |
1 | 在该界面中,上面的一排目录按钮(即“usr”、“local”、“hadoop”、“share”、“hadoop”、“mapreduce”和“lib”),当点击某个目录按钮时,就会在下面列出该目录的内容。 |

编写Java应用程序代码
1 | import org.apache.hadoop.conf.Configuration; |
1 | 这行代码给出了需要被检测的文件名称是“test”,没有给出路径全称,表示是采用了相对路径,实际上就是测试当前登录Linux系统的用户hadoop,在HDFS中对应的用户目录下是否存在test文件,也就是测试HDFS中的“/user/hadoop/”目录下是否存在test文件。 |
编译运行程序
1 | cd /usr/local/hadoop |
1 | 现在就可以编译运行上面编写的代码。可以直接点击Eclipse工作界面上部的运行程序的快捷按钮,当把鼠标移动到该按钮上时,在弹出的菜单中选择“Run As”,继续在弹出来的菜单中选择“Java Application”,如图4-12所示。 |
1 | 在该界面中,需要在“Select type”下面的文本框中输入“HDFSFileIfExist”,Eclipse就会自动找到相应的类“HDFSFileIfExist-(default package)”(注意:这个类在后面的导出JAR包操作中的Launch configuration中会被用到),然后,点击界面右下角的“OK”按钮,开始运行程序。程序运行结束后,会在底部的“Console”面板中显示运行结果信息(如图4-14所示)。由于目前HDFS的“/user/hadoop”目录下还没有test文件,因此,程序运行结果是“文件不存在”。同时,“Console”面板中还会显示一些类似“log4j:WARN…”的警告信息,可以不用理会。 |
应用程序的部署
1 | 下面介绍如何把Java应用程序生成JAR包,部署到Hadoop平台上运行。首先,在Hadoop安装目录下新建一个名称为myapp的目录,用来存放我们自己编写的Hadoop应用程序 |
1 | 然后,请在Eclipse工作界面左侧的“Package Explorer”面板中,在工程名称“HDFSExample”上点击鼠标右键,在弹出的菜单中选择“Export”,如图4-15所示。 |
1 | 在该界面中,“Launch configuration”用于设置生成的JAR包被部署启动时运行的主类,需要在下拉列表中选择刚才配置的类“HDFSFileIfExist-HDFSExample”。在“Export destination”中需要设置JAR包要输出保存到哪个目录,比如,这里设置为“/usr/local/hadoop/myapp/HDFSExample.jar”。在“Library handling”下面选择“Extract required libraries into generated JAR”。然后,点击“Finish”按钮,会出现如图4-18所示界面。 |

1 | 可以忽略该界面的信息,直接点击界面右下角的“OK”按钮。至此,已经顺利把HDFSExample工程打包生成了HDFSExample.jar。 |
1 | 现在,就可以在Linux系统中,使用hadoop jar命令运行程序,命令如下: |
1 | 或者也可以使用如下命令运行程序: |
附录:自己练习用的代码文件
1 | import org.apache.hadoop.conf.Configuration; |
1 | import org.apache.hadoop.conf.Configuration; |
1 | import java.io.BufferedReader; |
1 | 注意!!!!!!!!!!!!!!!! |
1 | import org.apache.hadoop.conf.Configuration; |