HDFS分布式文件系统
1. HDFS概述
- 在现代的企业环境中,单机容量往往无法存储大量数据,需要跨机器存储。统一管理分布在集群上的文件系统称为分布式文件系统 。
- HDFS(Hadoop Distributed File System)是 Apache Hadoop 项目的一个子项目. Hadoop 非常适于存储大型数据 (比如 TB 和 PB), 其就是使用 HDFS 作为存储系统. HDFS 使用多台计算机存储文件, 并且提供统一的访问接口, 像是访问一个普通文件系统一样使用分布式文件系统.
- 分布式文件系统解决的问题就是大数据存储。它们是横跨在多台计算机上的存储系统。分布式文件系统在大数据时代有着广泛的应用前景,它们为存储和处理超大规模数据提供所需的扩展能力。

- 如何实现HDFS 分布式文件系统?
HDFS 就是一个软件,实现将多个服务器的磁盘进行统一管理,构建出来一个更大的存储空间16T的大小,数据都是保存在每个节点上
2. HDFS发展历史
- Doug Cutting 在做 Lucene 的时候, 需要编写一个爬虫服务, 这个爬虫写的并不顺利, 遇到 了一些问题, 诸如: 如何存储大规模的数据, 如何保证集群的可伸缩性, 如何动态容错等。
- 2003年的时候, Google 发布了三篇论文, 被称作为三驾马车, 其中有一篇叫做 GFS, 是描述了 Google 内部的一个叫做 GFS 的分布式大规模文件系统, 具有强大的可伸缩性和容错。
- Doug Cutting 后来根据 GFS 的论文, 创造了一个新的文件系统, 叫做 HDFS。
-
3. HDFS设计目标
- 硬件故障是常态, HDFS将有成百上千的服务器组成,每一个组成部分都有可能出现故障。因此故障的检测和自动快速恢复是HDFS的核心架构目标。
- HDFS上的应用与一般的应用不同,它们主要是以流式读取数据。HDFS被设计成适合批量处理,而不是用户交互式的。相较于数据访问的反应时间,更注重数据访问的高吞吐量。
- 典型的HDFS文件大小是GB到TB的级别。所以,HDFS被调整成支持大文件。它应该提供很高的聚合数据带宽,一个集群中支持数百个节点,一个集群中还应该支持千万级别的文件。
- 大部分HDFS应用对文件要求的是write-one-read-many访问模型。一个文件一旦创建、写入、关闭之后就不需要修改了。这一假设简化了数据一致性问题,使高吞吐量的数据访问成为可能。
- 移动计算的代价比之移动数据的代价低。一个应用请求的计算,离它操作的数据越近就越高效,这在数据达到海量级别的时候更是如此。将计算移动到数据附近,比之将数据移动到应用所在显然更好。
- 在异构的硬件和软件平台上的可移植性。这将推动需要大数据集的应用更广泛地采用HDFS作为平台。
4. HDFS应用场景
4.1. 适合的应用场景
- 存储非常大的文件:这里非常大指的是几百M、G、或者TB级别,需要高吞吐量,对延时没有要求。
- 采用流式的数据访问方式: 即一次写入、多次读取,数据集经常从数据源生成或者拷贝一次,然后在其上做很多分析工作 ,且不支持文件的随机修改。
- 正因为如此,HDFS适合用来做大数据分析的底层存储服务,并不适合用来做.网盘等应用,因为,修改不方便,延迟大,网络开销大,成本太高。
- 运行于商业硬件上: Hadoop不需要特别贵的机器,可运行于普通廉价机器,可以处节约成本
- 需要高容错性
- 为数据存储提供所需的扩展能力
4.2. 不适合的应用场景
- 低延时的数据访问 对延时要求在毫秒级别的应用,不适合采用HDFS。HDFS是为高吞吐数据传输设计的,因此可能牺牲延时
- 大量小文件 文件的元数据保存在NameNode的内存中, 整个文件系统的文件数量会受限于NameNode的内存大小。 经验而言,一个文件/目录/文件块一般占有150字节的元数据内存空间。如果有100万个文件,每个文件占用1个文件块,则需要大约300M的内存。因此十亿级别的文件数量在现有商用机器上难以支持。
- 多方读写,需要任意的文件修改 HDFS采用追加(append-only)的方式写入数据。不支持文件任意offset的修改,HDFS适合用来做大数据分析的底层存储服务,并不适合用来做.网盘等应用,因为,修改不方便,延迟大,网络开销大,成本太高。
5. HDFS的架构
HDFS采用Master/Slave架构,一个HDFS集群有两个重要的角色,分别是Namenode和Datanode。Namenode是管理节点,负责管理文件系统的命名空间(namespace)以及客户端对文件的访问。Datanode是实际存储数据的节点。HDFS暴露了文件系统的命名空间,用户能够以操作文件的形式在上面操作数据。- HDFS的四个基本组件:HDFS Client、NameNode、DataNode 和 Secondary NameNode。

1、Client:就是客户端。
- 文件切分。文件上传 HDFS 的时候,Client 将文件切分成 一个一个的Block,然后进行存储
- 与 NameNode 交互,获取文件的位置信息。
- 与 DataNode 交互,读取或者写入数据。
- Client 提供一些命令来管理 和访问HDFS,比如启动或者关闭HDFS。
2、NameNode:就是 master,它是一个主管、管理者。
- 管理 HDFS 的名称空间
- 管理数据块(Block)映射信息
- 配置副本策略
- 处理客户端读写请求。
3、DataNode:就是Slave。NameNode 下达命令,DataNode 执行实际的操作。
- 存储实际的数据块。
- 执行数据块的读/写操作。
4、Secondary NameNode:并非 NameNode 的热备。当NameNode 挂掉的时候,它并不能马上替换 NameNode 并提供服务。
- 辅助 NameNode,分担其工作量。
- 定期合并 fsimage和fsedits,并推送给NameNode。
- 在紧急情况下,可辅助恢复 NameNode。
6. HDFS的副本机制
6.1. HDFS文件副本机制
- HDFS被设计成能够在一个大集群中跨机器可靠地存储超大文件。它将每个文件存储成一系列的数据块,这个数据块被称为block,除了最后一个,所有的数据块都是同样大小的。
- 为了容错,文件的所有block都会有副本。每个文件的数据块大小和副本系数都是可配置的。
- 所有的文件都是以 block 块的方式存放在 HDFS 文件系统当中,作用如下
- 一个文件有可能大于集群中任意一个磁盘,引入块机制,可以很好的解决这个问题
- 使用块作为文件存储的逻辑单位可以简化存储子系统
- 块非常适合用于数据备份进而提供数据容错能力
- 副本优点是安全,缺点是占空间。
- 在 Hadoop1 当中, 文件的 block 块默认大小是 64M, hadoop2 当中, 文件的 block 块大小默认是 128M(134217728字节)。假设文件大小是100GB,从字节位置0开始,每128MB字节划分为一个block,依此类推,可以划分出很多的block。每个block就是128MB大小。
- block块的大小可以通过 hdfs-site.xml 当中的配置文件进行指定,Hadoop默认的副本数为3,也就是每个block会存三份。
#修改文件的路径为 /export/server/hadoop-2.7.5/etc/hadoop/hdfs-site.xml <!-- 设置一个文件切片的大小:128M--> <property> <name>dfs.blocksize</name> <value>134217728</value> </property> <!-- 文件切片的副本个数--> <property> <name>dfs.replication</name> <value>3</value> </property>
注意当一个文件的大小不足128M时,比如文件大小为2M,那么这个文件也占用一个block,但是这个block实际只占2M的空间,所以从某种意义上来讲,block只是一个逻辑单位。
6.2. HDFS副本放置策略(机架感知):
HDFS分布式文件系统的内部有一个副本存放策略,默认副本数为3,在这里以副本数=3为例:
- 第一副本:优先放置到离写入客户端最近的DataNode节点,如果上传节点就是DataNode,则直接上传到该节点,如果是集群外提交,则随机挑选一台磁盘不太慢,CPU不太忙的节点。
- 第二个副本:放置在与第一个同机架的不同机器中
- 第三个副本:放置在另一个机架中, 某一个服务器中

7. HDFS的Shell命令行使用
7.1. Shell命令行客户端
- HDFS是存取数据的分布式文件系统,那么对HDFS的操作,就是文件系统的基本操作,比如文件的创建、修改、删除、修改权限等,文件夹的创建、删除、重命名等。对HDFS的操作命令类似于Linux的shell对文件的操作,如ls、mkdir、rm等。
- Hadoop提供了文件系统的shell命令行客户端,使用方法如下:
|
hadoop fs <args> |
- 文件系统shell包括与Hadoop分布式文件系统(HDFS)以及Hadoop支持的其他文件系统(如本地FS,HFTP FS,S3 FS等)直接交互的各种类似shell的命令。
- 所有FS shell命令都将路径URI作为参数。URI格式为scheme://authority/path。对于HDFS,该scheme是hdfs,对于本地FS,该scheme是file。scheme和authority是可选的。如果未指定,则使用配置中指定的默认方案。
- 对于HDFS,命令示例如下:
|
hadoop fs -ls hdfs://namenode:host/parent/child hadoop fs -ls /parent/child #hdfs-site.xml中的fs.defaultFS中有配置 |
- 对于本地文件系统,命令示例如下:
|
hadoop fs -ls file:///root/ |
如果使用的文件系统是HDFS,则也可使用hdfs dfs <args>命令。
7.2. Shell命令选项
|
选项名称 |
使用格式 |
含义 |
|
-ls |
-ls <路径> |
查看指定路径的当前目录结构 |
|
-lsr |
-lsr <路径> |
递归查看指定路径的目录结构 |
|
-du |
-du <路径> |
统计目录下个文件大小 |
|
-dus |
-dus <路径> |
汇总统计目录下文件(夹)大小 |
|
-count |
-count [-q] <路径> |
统计文件(夹)数量 |
|
-mv |
-mv <源路径> <目的路径> |
移动 |
|
-cp |
-cp <源路径> <目的路径> |
复制 |
|
-rm |
-rm [-skipTrash] <路径> |
删除文件/空白文件夹 |
|
-rmr |
-rmr [-skipTrash] <路径> |
递归删除 |
|
-put |
-put <多个linux上的文件> <hdfs路径> |
上传文件 |
|
-copyFromLocal |
-copyFromLocal <多个linux上的文件> <hdfs路径> |
从本地复制 |
|
-moveFromLocal |
-moveFromLocal <多个linux上的文件> <hdfs路径> |
从本地移动 |
|
-getmerge |
-getmerge <源路径> <linux路径> |
合并到本地 |
|
-cat |
-cat <hdfs路径> |
查看文件内容 |
|
-text |
-text <hdfs路径> |
查看文件内容 |
|
-copyToLocal |
-copyToLocal [-ignoreCrc] [-crc] [hdfs源路径] [linux目的路径] |
从本地复制 |
|
-moveToLocal |
-moveToLocal [-crc] <hdfs源路径> <linux目的路径> |
从本地移动 |
|
-mkdir |
-mkdir <hdfs路径> |
创建空白文件夹 |
|
-setrep |
-setrep [-R] [-w] <副本数> <路径> |
修改副本数量 |
|
-touchz |
-touchz <文件路径> |
创建空白文件 |
|
-stat |
-stat [format] <路径> |
显示文件统计信息 |
|
-tail |
-tail [-f] <文件> |
查看文件尾部信息 |
|
-chmod |
-chmod [-R] <权限模式> [路径] |
修改权限 |
|
-chown |
-chown [-R] [属主][:[属组]] 路径 |
修改属主 |
|
-chgrp |
-chgrp [-R] 属组名称 路径 |
修改属组 |
|
-help |
-help [命令选项] |
帮助 |
格式: hadoop fs -ls URI 作用:类似于Linux的ls命令,显示文件列表 hadoop fs -ls / 格式 : hdfs dfs -lsr URI 作用 : 在整个目录下递归执行ls, 与UNIX中的ls-R类似 hdfs dfs -ls -R / 格式 : hdfs dfs -mkdir [-p] <paths> 作用 : 以<paths>中的URI作为参数,创建目录。使用-p参数可以递归创建目录 hadoop fs -mkdir /dir1 hadoop fs -mkdir /dir2 hadoop fs -p -mkdir /aaa/bbb/ccc 格式 : hadoop fs -put <localsrc > ... <dst> 作用 : 将单个的源文件src或者多个源文件srcs从本地文件系统拷贝到目标文件系统中(<dst>对应的路径)。也可以从标准输入中读取输入,写入目标文件系统中 echo “Hello HDFS” >> /root/1.txt hadoop fs -put /root/1.txt /dir1 格式: hdfs dfs -moveFromLocal <localsrc> <dst> 作用: 和put命令类似,但是源文件localsrc拷贝之后自身被删除 echo “Hello HDFS” >> /root/2.txt hdfs dfs -moveFromLocal /root/2.txt / 格式: hadoop fs -get [-ignorecrc ] [-crc] <src> <localdst> 作用: 将文件拷贝到本地文件系统。 CRC 校验失败的文件通过-ignorecrc选项拷贝。 文件和CRC校验和可以通过-CRC选项拷贝 hadoop fs -get /2.txt /export/data 格式: hadoop fs -getmerge -nl < hdfs dir > < local file > 功能:合并下载多个文件 参数: 加上nl后,合并到local file中的hdfs文件之间会空出一行 示例:比如hdfs的目录 /aaa/下有多个文件:log.1, log.2,log.3,... hadoop fs -getmerge /aaa/log.* ./log.sum 格式 : hdfs dfs -mv URI <dest> 作用: 将hdfs上的文件从原路径移动到目标路径(移动之后文件删除),该命令不能夸文件系统 hdfs dfs -mv /dir1/a.txt /dir2 格式: hadoop fs -rm [-r] 【-skipTrash】 URI 【URI 。。。】 作用: 删除参数指定的文件和目录,参数可以有多个,删除目录需要加-r参数 如果指定-skipTrash选项,那么在回收站可用的情况下,该选项将跳过回收站而直接删除文件; 否则,在回收站可用时,在HDFS Shell 中执行此命令,会将文件暂时放到回收站中。 hadoop fs -rm /2.txt #删除文件 hadoop fs -rm -r /dir1 #删除目录 格式: hdfs dfs -cp URI [URI ...] <dest> 作用:将文件拷贝到目标路径中。如果<dest> 为目录的话,可以将多个文件拷贝到该目录下。 -f 选项将覆盖目标,如果它已经存在。 -p 选项将保留文件属性(时间戳、所有权、许可、ACL、XAttr)。 hadoop fs -cp /dir1/1.txt /dir2/2.txt hadoop fs -cat URI [uri ...] 作用:将参数所指示的文件内容输出到控制台 hadoop fs -cat /dir2/2.txt hadoop fs -cat URI 功能:显示目录中所有文件大小,当只指定一个文件时,显示此文件的大小。 hadoop fs -du / 格式: hadoop fs -chmod [-R] URI[URI ...] 作用: 改变文件权限。如果使用 -R 选项,则对整个目录有效递归执行。使用这一命令的用户必须是文件的所属用户,或者超级用户。 例如:可以创建一个用户hadoop,将/a.txt的所属用户和所属用户组修改为hadoop hadoop fs -chmod -R 777 /dir1 格式: hdfs dfs -chmod [-R] URI[URI ...] 作用:改变文件的所属用户和用户组。如果使用 -R 选项,则对整个目录有效递归执行。使用这一命令的用户必须是文件的所属用户,或者超级用户。 hadoop fs -chown -R hadoop:hadoop /a.txt 格式: hadoop fs -appendToFile <localsrc> ... <dst> 作用: 追加一个或者多个文件到hdfs指定文件中.也可以从命令行读取输入. cd /export/server/hadoop2.7.5/etc/hadoop/ hadoop fs -appendToFile *.xml /big.xml
7.1. HDFS的安全模式
- 安全模式是hadoop的一种保护机制,用于保证集群中的数据块的安全性。当集群启动的时候,会首先进入安全模式。当系统处于安全模式时会检查数据块的完整性。
- 假设我们设置的副本数(即参数dfs.replication)是3,那么在datanode上就应该有3个副本存在,假设只存在2个副本,那么比例就是2/3=0.666。hdfs默认的副本率0.999。我们的副本率0.666明显小于0.999,因此系统会自动的复制副本到其他dataNode,使得副本率不小于0.999。如果系统中有5个副本,超过我们设定的3个副本,那么系统也会删除多于的2个副本。
- 在安全模式状态下,文件系统只接受读数据请求,而不接受删除、修改等变更请求。在当整个系统达到安全标准时,HDFS自动离开安全模式。
安全模式操作命令
|
hdfs dfsadmin -safemode get #查看安全模式状态 hdfs dfsadmin -safemode enter #进入安全模式 hdfs dfsadmin -safemode leave #离开安全模式 |
1.2. HDFS基准测试
- 实际生产环境当中,hadoop的环境搭建完成之后,第一件事情就是进行压力测试,测试我们的集群的读取和写入速度,测试我们的网络带宽是否足够等一些基准测试
1.2.1. 测试写入速度
向HDFS文件系统中写入数据,10个文件,每个文件10MB,文件存放到/benchmarks/TestDFSIO中
|
hadoop jar /export/servers/hadoop-2.7.5/share/hadoop/mapreduce/hadoop-mapreduce-client-jobclient-2.7.5.jar TestDFSIO -write -nrFiles 10 -fileSize 10MB |
完成之后查看写入速度结果
|
hadoop fs -text /benchmarks/TestDFSIO/io_write/part-00000 |
1.2.2. 测试读取速度
测试hdfs的读取文件性能
在HDFS文件系统中读入10个文件,每个文件10M
|
hadoop jar /export/servers/hadoop-2.7.5/share/hadoop/mapreduce/hadoop-mapreduce-client-jobclient-2.7.5.jar TestDFSIO -read -nrFiles 10 -fileSize 10MB |
查看读取果
|
hadoop fs -text /benchmarks/TestDFSIO/io_read/part-00000 |
1.2.3. 清除测试数据
|
hadoop jar /export/servers/hadoop-2.7.5/share/hadoop/mapreduce/hadoop-mapreduce-client-jobclient-2.7.5.jar TestDFSIO -clean |
8.HDFS基本原理
namenode的原理
-
NameNode在内存中保存着整个文件系统的名称空间和文件数据块的地址映射,整个HDFS可存储的文件数受限于NameNode的内存大小 。
-
NameNode元数据信息 文件名,文件目录结构,文件属性(生成时间,副本数,权限)每个文件的块列表。 以及列表中的块与块所在的DataNode之间的地址映射关系 在内存中加载文件系统中每个文件和每个数据块的引用关系(文件、block、datanode之间的映射信息) 数据会定期保存到本地磁盘(fsImage文件和edits文件)
dataNode副本文件数据块到底存放到哪些DataNode上,是由NameNode决定的,NameNode根据全局情况做出放置副本的决定
NameNode心跳机制全权管理数据块的复制,周期性的接受心跳和块的状态报告信息(包含该DataNode上所有数据块的列表) 若接受到心跳信息,NameNode认为DataNode工作正常,如果在10分钟后还接受到不到DataNode的心跳,那么NameNode认为DataNode已经宕机 ,这时候NN准备要把DN上的数据块进行重新的复制。 块的状态报告包含了一个DataNode上所有数据块的列表,blocks report 每隔1小时发送一次.

datanode的原理
-
Data Node以数据块的形式存储HDFS文件
-
DataNode也称为Slave。
-
NameNode和DataNode会保持不断通信。
-
DataNode启动时,它将自己发布到NameNode并汇报自己负责持有的块列表。
-
当某个DataNode关闭时,它不会影响数据或群集的可用性。NameNode将安排由其他DataNode管理的块进行副本复制。
-
DataNode所在机器通常配置有大量的硬盘空间。因为实际数据存储在DataNode中。
-
DataNode会定期(dfs.heartbeat.interval配置项配置,默认是3秒)向NameNode发送心跳,如果NameNode长时间没有接受到DataNode发送的心跳, NameNode就会认为该DataNode失效。timeout = 2 * heartbeat.recheck.interval + 10 * dfs.heartbeat.interval,而默认的heartbeat.recheck.interval 大小为5分钟(单位毫秒),dfs.heartbeat.interval默认的大小为3秒。所以namenode如果在10分钟+30秒后,仍然没有收到datanode的心跳,就认为datanode已经宕机,并标记为dead。
-
datanode中的数据block汇报时间间隔取参数dfs.blockreport.intervalMsec,参数未配置的话默认为6小时.
HDFS的工作机制
HDFS的写入机制
写入机制流程:

详细步骤解析:
-
client发起文件上传请求,通过RPC与NameNode建立通讯,NameNode检查目标文件是否已存在,父目录是否存在,返回是否可以上传;
-
client请求第一个 block该传输到哪些DataNode服务器上;
-
NameNode根据配置文件中指定的备份数量及副本放置策略进行文件分配,返回可用的DataNode的地址,如:A,B,C;
-
client请求3台DataNode中的一台A上传数据(本质上是一个RPC调用,建立pipeline),A收到请求会继续调用B,然后B调用C,将整个pipeline建立完成,后逐级返回client;
-
client开始往A上传第一个block(先从磁盘读取数据放到一个本地内存缓存),以packet为单位(默认64K),A收到一个packet就会传给B,B传给C;A每传一个packet会放入一个应答队列等待应答。
-
数据被分割成一个个packet数据包在pipeline上依次传输,在pipeline反方向上,逐个发送ack(命令正确应答),最终由pipeline中第一个DataNode节点A将pipeline ack发送给client;
-
当一个block传输完成之后,client再次请求NameNode上传第二个block到服务器。
HDFS的读取机制

详细步骤解析:
-
Client向NameNode发起RPC请求,来确定请求文件block所在的位置;
-
NameNode会视情况返回文件的部分或者全部block列表,对于每个block,NameNode都会返回含有该block副本的DataNode地址;
-
这些返回的DN地址,会按照集群拓扑结构得出DataNode与客户端的距离,然后进行排序,排序两个规则:网络拓扑结构中距离Client近的排靠前;心跳机制中超时汇报的DN状态为STALE,这样的排靠后;
-
Client选取排序靠前的DataNode来读取block,如果客户端本身就是DataNode,那么将从本地直接获取数据;底层上本质是建立Socket Stream(FSDataInputStream),重复的调用父类DataInputStream的read方法,直到这个块上的数据读取完毕;
-
当读完列表的block后,若文件读取还没有结束,客户端会继续向NameNode获取下一批的block列表;
-
读取完一个block都会进行checksum验证,如果读取DataNode时出现错误,客户端会通知NameNode,然后再从下一个拥有该block副本的DataNode继续读。
-
read方法是并行的读取block信息,不是一块一块的读取;NameNode只是返回Client请求包含块的DataNode地址,并不是返回请求块的数据;
最终读取来所有的block会合并成一个完整的最终文件。
HDFS的元数据辅助管理
主要功能
将 edits 文件和 fsimage 文件进行合并操作,形成新的fsimage 文件。

snn 元数据辅助执行流程
第一步:将hdfs更新记录写入一个新的文件——edits.new。
第二步:将fsimage和editlog通过http协议发送至secondary namenode。
第三步:将fsimage与editlog合并,生成一个新的文件——fsimage.ckpt。这步之所以要在secondary namenode中进行,是因为比较耗时,如果在namenode中进行,或导致整个系统卡顿。
第四步将生成的fsimage.ckpt通过http协议发送至namenode。
第五步重命名fsimage.ckpt为fsimage,edits.new为edits。
第六步等待下一次checkpoint触发SecondaryNameNode进行工作,一直这样循环操作。
fsimage的信息查看
cd /export/server/hadoop2.7.5/hadoopDatas/namenodeDatas
hdfs oiv -i fsimage_0000000000000000864 -p XML -o fsimage.xml
edits的文件查看
cd /export/server/hadoop2.7.5/hadoopDatas/namenodeDatas
hdfs oev -i edits_0000000000000000865-0000000000000000866 -p XML -o myedit.xml

浙公网安备 33010602011771号