文章目录





介绍

在现代的企业环境中,单机容量旺旺无法存储大量的数据,需要跨机器存储。统一管理分布在集群上的文件系统称为分布式文件系统。

HDFS(Hadoop Distributed File System)是Apache Hadoop项目的一个子项目。HDFS非常适合存储大型的数据(比如TB和PB),他用多台计算机存储文件,并且提供统一的访问接口,像是访问一个普通的文件系统一样使用分布式文件系统。

适合的场景

存储非常大的文件: 这里面指几百M G或者TB级别,需要高吞吐量,对延时没有要求。

采用流式的数据访问;即一次写入、多次读取,数据集经常从数据源生成或者拷贝一次,然后在其上做很多分析工作。

运行于商业硬件上:Hadoop不需要特别贵的机器,可运行于普通廉价的机器,可以节约成本

需要很高的容错性

为数据存储提供所需的扩展能力

不适合的场景

低延时的数据访问,对延时要求在毫秒级别的应用,不适合采用HDFS。HDFS十位高吞吐数据传输设计的,因此肯呢个牺牲延时。

大量的小文件 文件元数据保存在NameNode的内存中,整个文件系统的数量会受到NameNode的内存大小的影响。经验而言,一个文件/目录/文件快一半占有150字节的元数据内存空间.如果有100万个文 件,每个文件占用1个文件块,则需300M内存.因此十亿级别的文件数量在现有的商用机上很难支持。

多方读写,需要任意的文件修改 HDFS采用追加的方式写入数据,不支持任意的修改。不支持多个写入器。

架构

HDFS是一个主从(Master、Slave)体系结构
HDFS由四部分组成,HDFS Client、NameNode、DataNode和Secondary NameNode

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-zzpl4UyC-1571929492900)(1B7574F32D194C9CB4BB26A05100B609)]

  • Client:就是客户端
文件切分,文件上传HDFS的时候,Client将文件切分成一个一个的Block,然后进行存储。

与NameNode交互,获取文件的位置信息。

与DataNode交互,获取文件的位置信息。

与DataNode交互,读取或者写入信息

Client提供一些命令来管理和访问HDFS,比如启动或者关闭HDFS。
  • NameNode:就是Master,它是一个主管、管理者
管理HDFS的名称空间

管理数据块(BLOCK)映射信息

配置副本策略

处理客户端读写的请求
  • DataNode:就是Slave.NameNode下达命令,DataNode执行实际的操作
存储实际的数据块

执行数据块的读写操作
  • Secondary NameNode:并非NameNode的热备.当NameNode挂掉的时候,它不能马上替换其工作
辅助NameNode, 分担其工作量

定期合并fsimage(镜像文件)和fsedits(日志文件 ), 并推送给NameNode

在紧急情况下, 可辅助恢复NameNode

NameNode和DataNode

  • NameNode的作用
NameNode在内存中保存着整个文件系统的名称空间和文件数据块的地址映射。
整个HDFS的可存储文件数收到NameNode的内存大小限制

1.NameNode元数据信息
文件名,文件目录结构,文件属性(生成时间、副本数、权限)每个文件的块列表。以及列表中块与块所在的DataNode之间的地址映射关系,在内存中健在文件系统中每个数据块的引用关系。数据会定期保存到磁盘(fsimage和edits文件)

2.文件操作
NameNode负责文件元数据的操作,Data负责处理文件内容的读写请求,数据流不断的经过NameNode,会询问它和哪个DataNode联系

3.NameNode副本
文件数据块到底存放到哪个DataNode上,是由NameNode决定的,NameNode会根据全局情况作出放置副本的决定

4.NameNode的心跳机制
全权管理数据块的复制,周期性的接受心跳和块的状态报告信息(包含该DataNode上所有数据块的列表) 若接受到心跳信息,NameNode认为DataNode工作正常,如果在10分钟后还接受到不到DN的心跳,那么NameNode认为DataNode已经宕机 ,这时候NN准备要把DN上的数据块进行重新的复制。 块的状态报告包含了一个DN上所有数据块的列表,blocks report 每个1小时发送一次.
  • DataNode的作用
1、Data Node以数据块的形式存储HDFS文件
2、Data Node 响应HDFS 客户端读写请求
3、Data Node 周期性向NameNode汇报心跳信息
4、Data Node 周期性向NameNode汇报数据块信息
5、Data Node 周期性向NameNode汇报缓存数据块信息

HDFS的副本机制和机架感知

  • 副本机制
所有的文件都是以 block 块的方式存放在 HDFS 文件系统当中,作用如下
1. 一个文件有可能大于集群中任意一个磁盘,引入块机制,可以很好的解决这个问题
2. 使用块作为文件存储的逻辑单位可以简化存储子系统
3. 块非常适合用于数据备份进而提供数据容错能力
在 Hadoop1 当中, 文件的 block 块默认大小是 64M, hadoop2 当中, 文件的 block 块大小默认是
128M, block 块的大小可以通过 hdfs-site.xml 当中的配置文件进行指定

<property>
<name>dfs.block.size</name>
<value>块大小 以字节为单位</value>
</property>
  • 机架感知
HDFS分布式文件系统的内部有一个副本存放策略:以默认的副本数=3为例:
1、第一个副本块存本机
2、第二个副本块存跟本机同机架内的其他服务器节点
3、第三个副本块存不同机架的一个服务器节点上

HDFS命令行使用

命令1 -ls(显示指定URL下的文件列表)
hdfs dfs -ls /

命令2 -ls -R(在整个目录下递归执行ls)
hdfs dfs -ls -R /

命令3 -mkdir(创建目录,使用 -p 可以递归创建目录)
hdfs dfs -p -mkdir

命令4 -put(将文件从本地文件系统拷贝到目标文件系统中)
hdfs dfs -put /export/1.txt /chenyang/1.txt

命令5 -moveFromLocal(和put命令类似,但是源文件拷贝之后自身会被删除)
hdfs dfs -moveFromLocal <localsrc> <dst>
ps: 暂时没有moveToLocal

命令6 -get(将文件系统的文件拷贝到本地)
hdfs dfs -get /chenyang/1.txt /export

命令7 -mv(将文件从文件系统的原路径移动到目标路径(移动之后的文件删除),该命令不能跨文件系统)
hdfs dfs -mv /dir1/1.txt /dir2

命令8 -rm(删除参数指定的文件如果指定了-skipTrash选项,会直接跳过回收站)
hdfs dfs -rm -r -skipTrash /dir1

命令9 -cp(将文件拷贝到目标路径,如果指定为目录的话,会将路径下的所有文件拷贝)
hdfs dfs -cp URI <dest>
ps:-f 如果目标文件存在,将其覆盖
-p 选项将保留文件属性(时间戳、所有权、许可、ACL、XAttr)

命令10 cat(查看文件内容)
hdfs dfs -cat /chenyang/1.txt

命令11 chmod(改变文件权限,如果-R选项,则对整个目录有效的递归执行。
使用这一命令必须是文件所属的用户,或者是超级用户)
hdfs dfs -chmod -R 777 /chenyang/1.txt

命令11 chown(改变文件的所属用户和用户组,如果使用-R选项,则对整个目录有效的递归执行。
使用这一命令必须是文件所属的用户,或者是超级用户)
hdfs dfs -chown -R hadoop:hadoop /chenyang/1.txt

命令12 appendToFile(追加一个或者多个文件到指定文件中,也可以使用命令行)
hdfs dfs -appendToFile a.xml b.xml /chenyang/1.txt

HDFS的高级命令使用

HDFS的文件限额配置

在多人共用HDFS环境下,配置设置十分重要。特别是在Hadoop处理大量资料的环境,如果没有配额管理,很容易吧空间用完造成别人没有办法存取。HDFS的配额设定是针对目录而不是针对账号。可以让每个账号仅操作某一个目录,然后对目录进行设置。

HDFS文件的限额配置允许我们以文件个数或者文件大小来限制我们在某个目录下上传的文件数量或者文件内容的总量,以便达到我们类似百度网盘等限制每个用户允许上传的最大的文件的量。
hdfs dfs -count -q -h /user/root/dir1 #查看配额信息

数量限额

# 设置文件夹能够上传的文件数量,设置的文件夹也算一个
hdfs dfsadmin -setQuota 2 /dir1

# 清除设置的数量限额
hdfs dfsadmin -clrQuota /dir1

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-linFqJ5E-1571929492902)(8EF23EA5A56E465EA0E2CD39374E7123)]

空间大小限额


在设置空间配额的时候,设置的空间大小至少是block_size * 3


# 限制空间大小为4K
hdfs dfsadmin -setSpaceQuota 4k /dir1

# 在当前目录下生成指定大小的文件
dd if=/dev/zero of=1.txt bs=1M count=2

# 清除空间配额的限制
hdfs dfsadmin -clrSpaceQuota /dir1

hdfs的安全模式

安全模式是hadoop的一种保护机制,用于保证集群中的数据块和安全性。当集群启动的时候,首先会进入安全模式。当系统处于安全模式的时候会检查数据块的完整性。

假设我们设置的副本数(即参数dfs.replication)是3,那么再datanode上就应该有三个副本存在,假设只存在2个副本的话,那么比例就是2/3=0.666。hdfs的默认副本率是0.999。我们的副本率0.666明显要小于0.999,因此系统会复制副本到其他的DataNode,使得副本率小于0.999。如果系统有五个副本,超过我们设定的3个副本,那么系统也会删除多余的两个副本。

在安全模式的状态下,文件系统只接受读数据的申请,而不接受删除、修改的请求。在整个系统达到安全标准的时候,HDFS会自动离开安全模式。

安全模式操作命令

hdfs dfsadmin -safamode get # 查看安全模式状态
hdfs dfsadmin -safemode enter # 进入安全模式
hdfs dfsadmin -safemode leave # 离开安全模式

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-cvh5Szav-1571929492903)(DDC9C5132D5748D5AECFC87744FFF3E0)]

HDFS基准测试

实际生产环境当中,hadoop的环境搭建完成之后,第一件事情就是进行压力测试,测试我们集群的读取和写入速度,测试我们网络带宽是否足够等的一些基准测试。

测试写入速度


向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

测试读取速度


测试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 jar /export/servers/hadoop-2.7.5/share/hadoop/mapreduce/hadoop-mapreduce-client-jobclient-2.7.5.jar TestDFSIO -clean
每次测试结束后会在测试的目录生成一个测试报告,清楚数据的命令不会删除此报告。

测试报告样例

----- TestDFSIO ----- : write
Date & time: Sun Oct 20 17:43:47 CST 2019
Number of files: 10
Total MBytes processed: 100
Throughput mb/sec: 54.02
Average IO rate mb/sec: 72.13
IO rate std deviation: 38.4
Test exec time sec: 8.84

----- TestDFSIO ----- : write
Date & time: Sun Oct 20 17:45:12 CST 2019
Number of files: 10
Total MBytes processed: 100
Throughput mb/sec: 81.5
Average IO rate mb/sec: 94.16
IO rate std deviation: 26.95
Test exec time sec: 5.52

----- TestDFSIO ----- : read
Date & time: Sun Oct 20 17:47:50 CST 2019
Number of files: 10
Total MBytes processed: 100
Throughput mb/sec: 220.26
Average IO rate mb/sec: 304.77
IO rate std deviation: 165.38
Test exec time sec: 4.4

HDFS文件的写入过程

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-yjuQwZR7-1571929492903)(38AE199B4DB84823AF3D5847481BA029)]

1.Client发起上传文件请求,通过RPC与NameNode建立通讯,NameNode检查目标文件是否已经存在,父目录是否存在,返回是否可以上传。
2.Client请求第一个block该传输到哪些DateNode服务器上。
3.NameNode根据配置文件中指定的备份数量和机架感知原理进行文件分配,返回可用的DataNode地址如:A、B、C
-》 Hadoop在设计的时候考虑到数据的安全与高效,数据文件默认在HDFS上存放三份,存储策略为本地一份,同机架内其他某一节点一份,不同机架上某一节点一份。
4.Client请求三台DateNode中的一台A上传数据,(本质上是一个RPC调用,建立pipeline),A收到请求之后会继续调用B,然后B调用C,将整个pipeline建立完成,后逐级返回Client。
5.Client开始往A上传第一个block(先从磁盘读取到本地内存缓存),以packet为单位(默认64k),A收到一个packet就会传给B,B传给C,A每传一个packet会放入一个应答队列等待应答。
6.数据被分割成一个个packet数据包在pipeline上一次传输,在piepline返方向上,逐个发送ack(命令正确应答),最终由piepline中第一个DataNode节点A将pipelineack发送给Client
7.当第一个block传输完成之后,Client会再一次请求NameNode上传第二个block。

HDFS文件的读取过程

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-WPu0yU5x-1571929492904)(54606AD676A244F28DCF34CE594B5D4E)]

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

HDFS的元数据辅助管理

在Hadoop的集群中,NameNode的所有元数据信息都保存在了FsImage和Edits文件当中,这两个文件就记录了所有的数据的元数据信息,元数据信息的保存目录配置在了hdfs-site.xml

<property>
<name>dfs.namenode.name.dir</name>
<value>
file:///export/servers/hadoop2.7.5/hadoopDatas/namenodeDatas,
file:///export/servers/hadoop-
2.7.5/hadoopDatas/namenodeDatas2
</value>
</property>
<property>
<name>dfs.namenode.edits.dir</name>
<value>file:///export/servers/hadoop-2.7.5/hadoopDatas/nn/edits</value>
</property>

FsImage和Edits详解

- edits
edits存放了客户端最近一段时间的操作日志。
客户端对HDFS进行写文件的时候首先会被记录在edits文件中。
edits修改元数据也会被更新。
- fsimage
NameNode中关于元数据的镜像,一般称为检查点,fsimage存放了一份比较完整的元数据信息。
因为fsimage是NameNode的完整镜像,如果每次都加载到内存中生成树状拓扑结构,是十分消耗内存和CPU的,所以一开始对NameNode的操作都放在edits中。
fsimage内容包含了NameNode管理下的所有DataNode文件以及文件block及block所在的DataNode的元数据信息。
随着edits内容的增大,就需要在一定时间点和fsimage合并。

fsimage中的文件信息查看

cd /export/servers/hadoop2.7.5/hadoopDatas/namenodeDatas
hdfs oiv -i fsimage_0000000000000000864 -p XML -o hello.xml

edits中的文件信息查看

cd /export/servers/hadoop2.7.5/hadoopDatas/namenodeDatas
hdfs oev -i edits_0000000000000000865-0000000000000000866 -p XML -o myedit.xml

SecondaryNameNode如何辅助管理fsimage与edits文件

SecondaryNameNode定期合并fsimage和edits,把edits控制在一个范围内
配置 SecondaryNameNode
SecondaryNameNode 在 conf/masters 中指定
在 masters 指定的机器上, 修改 hdfs-site.xml
<property>
<name>dfs.http.address</name>
<value>host:50070</value>
</property>

修改 core-site.xml , 这一步不做配置保持默认也可以
<!-- 多久记录一次 HDFS 镜像, 默认 1小时 -->
<property>
<name>fs.checkpoint.period</name>
<value>3600</value>
</property>
<!-- 一次记录多大, 默认 64M -->
<property>
<name>fs.checkpoint.size</name>
<value>67108864</value>
</property>

1. SecondaryNameNode 通知 NameNode 切换 editlog
2. SecondaryNameNode 从 NameNode 中获得 fsimage 和 editlog(通过http方式)
3. SecondaryNameNode 将 fsimage 载入内存, 然后开始合并 editlog, 合并之后成为新的
fsimage
4. SecondaryNameNode 将新的 fsimage 发回给 NameNode
5. NameNode 用新的 fsimage 替换旧的 fsimage

JAVA-API 代码

码云地址:
https://gitee.com/yang_hang/hdfs-demo.git