HDFS是Hadoop的一个重要组件,提供了分布式系统的文件存储,下面就我学习到的知识点整理一下吧
一、相关概念
- HDFS:Hadoop Distributed File Sysytem,即Hadoop分布式文件系统,以流式数据访问模式基于块(Block)来存储超大文件,是一个用来管理网络中跨多台计算机存储的文件系统;
- HDFS Block:HDFS是基于数据块来存储文件数据的,现在的版本中这个块的大小是128MB,稍早的版本是64M;
- 注意,HDFS的优缺点分明,优点:分布式存储以及分布式存储带来的优点,缺点:时延长,不适合频繁修改文件...(所以HDFS是不适合做网盘系统的)
- HDFS系统架构
- HDFS可以分为两大组件:NameNode和DataNode
- NameNode:主要负责管理文件系统的命名空间以及客户端对文件系统元数据的访问,即文件元数据的操作;当NameNode接收到DataNode报告的数据原信息的时候就会进行相应的检查,如果数据损坏就会根据设置的副本个数和DataNode节点决定是否要新增副本个数;NameNode的两个组成部分:
fsimage
:元数据镜像文件(保存文件系统的目录树)edits
:元数据操作日志(针对目录树的修改操作);SecondaryNameNode负责定期通过edits
来维护fsimage
; - DataNode:负责处理本节点上的块数据的读写请求;需要注意的是,这些请求是直接由客户端连接上来的,而能请求到具体的某个DataNode,是因为NameNode告诉客户端数据的具体存放位置;DataNode启动后向NameNode注册,注册成功后,为了保证数据的安全性,这个DataNode会周期性心跳的方式(dfs.blockreport.intervalMsec)向NameNode上报告所有的块信息,如果这个DataNode某些数据出现异常,NameNode就会重建这个DataNode的副本;
- 超时判断:当NameNode得不到DataNode的心跳请求的时候,不会立即认为该DataNode挂掉,而是等待一定的超时时间,超时时间的计算公式为:
2 * heartbeat.recheck.interval + 10 * dfs.heartbeat.interval
;默认情况下heartbeat.recheck.interval
为5分钟,默认单位为毫秒,dfs.heartbeat.interval
为3秒,默认单位为秒;
- 超时判断:当NameNode得不到DataNode的心跳请求的时候,不会立即认为该DataNode挂掉,而是等待一定的超时时间,超时时间的计算公式为:
- NameNode:主要负责管理文件系统的命名空间以及客户端对文件系统元数据的访问,即文件元数据的操作;当NameNode接收到DataNode报告的数据原信息的时候就会进行相应的检查,如果数据损坏就会根据设置的副本个数和DataNode节点决定是否要新增副本个数;NameNode的两个组成部分:
- HDFS可以分为两大组件:NameNode和DataNode
- HDFS的特性
- HDFS的包容性:无论单个文件多大,也无论这个文件是结构化的,非结构化的还是半结构化的,HDFS都能帮我们很好的存储这些数据;
- 可靠性/容错性:在配置HDFS的时候,我们都会在hdfs-site.xml中配置一个参数dfs.replication,这个参数就是用来配置,每个文件的副本个数,至于这些副本存储在哪里,是由NameNode决定的。
- 数据完整性:HDFS会经常去检查存储的文件的完整性,如果发现数据不完整,就会向NameNode报告,NameNode就会重新建立副本,以保证副本数量。
- 高吞吐量:正式由于分布式的原因,使得HDFS的吞吐量大大的增加,增大的部分和这个分布式集群的节点个数是成正比的;
- 高性能:说HDFS高性能是因为:一般情况下我们处理数据的时候都会把数据全部带到应用层上,然而HDFS中,可以直接把处理程序也做成集群,然后每个节点上都有一个数据处理程序,这样就避免了大量的磁盘甚至网络IO,处理的性能大大提高。
二、HDFS读写流程
-
文件写入流程
- 客户端请求处理上传文件,向NameNode请求上传文件,NameNode会查询内部的元数据,这个文件是否已经存在,如果已经存在,拒绝;如果不存在,则判断这个路径是否存在,如果不存在,则拒绝;否则批准上传;
- 请求同一个数据块的副本个Block地址;该客户端在计算数据大小之后向NameNode请求Block块,NameNode就返回这个Block块的所有副本地址,在这里NameNode在选择Block的时候会考虑:每个DataNode节点的空间使用量和客户端与这些DataNode之间的网络距离(数据包转发次数)等,综合这些因素,返回的所有Block会分散,以保证数据的安全;
- 客户端开始与DataNode建立连接;首先,先与第一台DataNode建立连接,如果所有的数据不在同一个DataNode上,第一台DataNode就会向后面的第二台DataNode建立连接,以通知第二台DataNode接收数据,同样的,如果还有,那么第二台就会向第三台DataNode请求连接...第三台DataNode响应给第二台DataNode,第二台DataNode响应给第一台,第一台相应给客户端,数据传输通道(pipline)建立成功;
-
开始传输数据;客户端通过socket把数据以packet形式传递给第一台,每次收到数据的DataNode都会以chunk(512byte)为单位对数据进行校验,然后第一台通过刚才与第二台的socket传递给第二台。。。然后又是倒着应答回客户端,如果一台机器失败了,传输完毕后由NameNode进行副本数量的维护;当第一个Block完成之后,如果还有数据就继续2步骤...
文件写入流程时序图
-
文件读入流程
- 客户端请求下载文件,NameNode就会读取存储的元数据,然后NameNode就会返回这个文件的元数据;
- 客户端拿到文件的元数据后,进行分析,与对应的DataNode建立数据传输通道,获取数据流;如果这个数据文件有多块,那么客户端会自动拼接这些Block文件,最终形成一个比较完整的文件;
-
NameNode的元数据管理
- NameNode中的数据存放在内存中,以保证元数据的访问速度;
- 当客户端向NameNode发送了写请求之后,在NameNode中更新元数据,并按照操作顺序记录操作日志
edits
,SecondaryNameNode和NameNode之间有心跳通信,SecondaryNameNode每一定时间就去询问NameNode是否需要触发SecondaryNameNode的checkpoint,NameNode就根据配置文件(checkpoint触发条件在配置文件中配置,要么定时,要么edits到了固定的数量)检查checkpoint的条件是否已经满足,如果条件满足,SecondaryNameNode就会向NameNode发出checkpoint的请求,接着NameNode就会触发edits
文件滚动一次,然后SecondaryNameNode就会下载NameNode中所有的fsimage...
和edits...
文件,然后SecondaryNameNode就会根据这些文件重新按照edits回放元数据操作过程,生成一个新的元数据集合,然后把这个新的元数据dump称为一个叫做fsimage.checkpoint
的文件,并上传至NameNode覆盖旧的fsimage
;后面再次触发checkpoint的时候就不会下载fsimage
文件了,只会下载edits...
文件; - NameNode和SecondaryNameNode的工作目录存储结构完全相同,所以当NameNode故障退出需要重新恢复时,可以从SecondaryNameNode的工作目录中将
fsimage
拷贝到NameNode的工作目录,便可恢复NameNode的数据; - SecondaryNameNode和NameNode的数据存储结构是一样的,所以,如果NameNode的name文件夹损坏,可以拷贝SecondaryNameNode的namesecondary为NameNode的name来恢复NameNode的数据,但是不一定能恢复所有的数据,损失的部分就是在损坏之前做checkpoint之后的写入数据;
- 如果避免NameNode的
edits
文件的安全呢?当然是把edits写到多个磁盘上即可,在hdfs-site.xml
中配置:<property> <name>dfs.name.dir</name> <value>$<disk1-hdp-data-dir>,$<disk2-hdp-data-dir></value> </property>
三、HDFS常用命令参数介绍
- 常用命令行参数
-
-help
- 功能:
输出这个命令参数手册
- 功能:
-
-ls
- 功能:显示目录信息
- 示例:
hadoop fs -ls hdfs://hadoop-server01:9000/
-
-mkdir
- 功能:在hdfs上创建目录
- 示例:
hadoop fs -mkdir -p /aaa/bbb/cc/dd
-
-moveFromLocal
- 功能:从本地剪切粘贴到hdfs
- 示例:
hadoop fs -moveFromLocal /home/hadoop/a.txt /aaa/bbb/cc/dd
-
-moveToLocal
- 功能:从hdfs剪切粘贴到本地
- 示例:
hadoop fs -moveToLocal /aaa/bbb/cc/dd /home/hadoop/a.txt
-
-appendToFile
- 功能:追加一个文件到已经存在的文件末尾
- 示例:
hadoop fs -appendToFile ./hello.txt hdfs://hadoop-server01:9000/hello.txt
- 简写:
Hadoop fs -appendToFile ./hello.txt /hello.txt
-
-cat
- 功能:显示文件内容
- 示例:
hadoop fs -cat /hello.txt
-
-tail
- 功能:显示一个文件的末尾
- 示例:
hadoop fs -tail /weblog/access_log.1
-
-text
- 功能:以字符形式打印一个文件的内容
- 示例:
hadoop fs -text /weblog/access_log.1
-
-chown/chmod/chgrp
- 功能:linux文件系统中的用法一样,对文件所属权限
- 示例:
hadoop fs -chmod 666 /hello.txt
hadoop fs -chown someuser:somegrp /hello.txt
-
-copyFromLocal
- 功能:从本地文件系统中拷贝文件到hdfs路径去
- 示例:
hadoop fs -copyFromLocal ./jdk.tar.gz /aaa/
-
-copyToLocal
- 功能:从hdfs拷贝到本地
- 示例:
hadoop fs -copyToLocal /aaa/jdk.tar.gz
-
-cp
- 功能:从hdfs的一个路径拷贝hdfs的另一个路径
- 示例:
hadoop fs -cp /aaa/jdk.tar.gz /bbb/jdk.tar.gz
-
-mv
- 功能:在hdfs目录中移动文件
- 示例:
hadoop fs -mv /aaa/jdk.tar.gz /
-
-get
- 功能:等同于copyToLocal,就是从hdfs下载文件到本地
- 示例:
hadoop fs -get /aaa/jdk.tar.gz
-
-getmerge
- 功能:合并下载多个文件
- 示例:
hadoop fs -getmerge /aaa/log.* ./log.sum
-
-put
- 功能:等同于copyFromLocal
- 示例:
hadoop fs -put /aaa/jdk.tar.gz /bbb/jdk.tar.gz
-
-rm
- 功能:删除文件或文件夹
- 示例:
hadoop fs -rm -r /aaa/bbb/
-
-rmdir
- 功能:删除空目录
- 示例:
hadoop fs -rmdir /aaa/bbb/ccc
-
-df
- 功能:统计文件系统的可用空间信息
- 示例:
hadoop fs -df -h /
-
-du
- 功能:统计文件夹的大小信息
- 示例:
hadoop fs -du -s -h /aaa/*
-
-count
- 功能:统计一个指定目录下的文件节点数量
- 示例:
hadoop fs -count /aaa/
-
-setrep
- 功能:设置hdfs中文件的副本数量
- 示例:
hadoop fs -setrep 3 /aaa/jdk.tar.gz
-
四、HDFS的常用命令操作
- 在HDFS上创建目录
hadoop fs -mkdir [-p] <dir-to-make>
- 上传文件
hadoop fs -put <file> <dir> # 或者 hdfs dfs -put <file> <dir>
- 查看状态
hdfs dfsadmin -report
五、API操作
- API操作就不在这里贴代码了
六、SafeMode
- 在NameNode的内存中,记录着所有的数据文件的副本数,数据文件分布式存储的块信息,以及这些块所在的DataNode的节点信息;
- 而在镜像中,相比NameNode的内存,少了这些块所在的DataNode的节点信息;
- 这里讲的SafeMode,NameNode启动的时候,值知道有哪些块,数据文件的副本数量,但是这些副本数量在各个NameNode节点的分布就不知道了,当DataNode在启动的时候,就会向NameNode汇报自己所持有的数据块信息;这样NameNode就会知道块所在的NameNode信息,NameNode数据信息才会补全,当NameNode的信息补全量达到99.8%的时候,才会推出SafeMode正常向外部提供服务;
七、Federation
- Federation讲的是对NameNode如何进行水平扩容;因为单个NameNode节点的容量始终是有限的,在大部分场景下都可以满足,当数据量超级大的少数情况下使用;
- 这里牵扯到ViewFS,即把两组机器当做两个目录挂载在HDFS上,一组机器有一个逻辑名称,为挂载的目录名称,访问的时候使用viewfs来访问两组机器,根据挂载的名称来路由到不同的机器组上;
- 每组机器为了HA而采用主备的思想;
- 对于DataNode而言,这些NameNode只相当于一个NameNode,是一个整体;