大数据知识点全讲解之HDFS
HDFS介绍
HDFS,Hadoop Distributed File System 是Apache Hadoop项目的一个子项目,Hadoop非常适于存储大型数据(比如TB或PB),其就是使用HDFS作为存储系统。HDFS使用多台计算机存储文件,并且提供统一的访问接口,像是访问一个普通文件系统一样使用分布式文件系统
HDFS应用场景
适合的场景:
- 存储非常大的文件:这里非常大是指几百M、G或者TB级别,需要高吞吐量,对延时没有要求
- 采用流式的数据访问方式:即一次写入,多次读取
- 节约成本
- 需要高容错性
- 要求有扩展能力
不适合的场景:
- 低延时的数据访问
- 大量小文件
- 多次读写
HDFS架构
HDFS由四部分组成:HDFS client、NameNode、DataNode、Secondary NameNode
Client
- 文件切分。文件上传HDFS的时候,Client将文件切分成一个一个的Block,然后进行存储
- 与NameNode交互,获取文件的位置信息
- 与DataNode交互,读取或者写入数据
- Client提供一些命令来管理和访问HDFS,比如启动或者关闭HDFS
NameNode
NameNode就是master,它是一个主管
- 管理HDFS的名称空间
- 管理数据块(block)映射信息
- 配置副本策略
- 处理客户端读写请求
DataNode
DataNode就是slave,NameNode下达命令,DataNode执行实际的操作
- 存储实际的数据块
- 执行数据块的读写操作
Secondary NameNode
它并非是NameNode的热备。当NameNode挂掉的时候,它并不能马上替代Namenode并提供服务
- 辅助NameNode,分担其工作量
- 定期合并fsimage的fsedits,并推送给NameNode
- 在紧急情况下,可以辅助恢复NameNode
Namenode的作用
- NameNode在内存中保存着整个文件系统的名称、空间和文件数据块的地址映射
- 整个HDFS可存储的文件数受限于NameNode的内存大小
1.NameNode元数据信息
文件名,文件目录结构,文件属性(生成时间,副本数,权限)每个文件的块列表,以及列表中的块与块所在的DataNode之间的地址映射关系。在内存中加载文件,系统中每个文件和每个数据块的引用关系(文件、block、datanode之间的映射信息)数据会定期保存到本地磁盘
2.NameNode文件操作
NameNode负责文件元数据的操作,DataNode负责处理文件内容的读写请求,数据流不经过NameNode,只会询问它跟哪个DataNode联系
3.NameNode副本
文件数据块到底存放到哪些DataNode上,是由NameNode决定的,NN根据全局情况作出放置副本的决定
4.NameNode心跳机制
全权管理数据块的复制,周期性的接受心跳和块的状态信息报告(包含该DataNode上所有数据块的列表)若接受到心跳信息,NameNode认为DataNode工作正常;如果在10分钟后还接受不到DN的心跳,那么NameNode认为DataNode已经宕机,这时候NN准备要把DN上的数据块进行重新赋值。块的状态报告包含了一个DN上所有数据块的列表,blocks report每小时发送一次
DataNode的作用
提供真实文件数据的存储服务
1.DataNode以数据块的形式存储HDFS文件
2.DataNode响应HDFS客户端读写请求
3.DataNode周期性向NameNode汇报心跳信息
4.DataNode周期性向NameNode汇报数据块信息
5.DataNode周期性向NameNode汇报缓存数据块信息
HDFS的副本机制
所有文件都是以block块的方式存放在HDFS文件系统当中,作用如下:
1.一个文件有可能大于集群中任意一个磁盘,引入块机制,可以很好的解决这个问题
2.使用块作为文件存储的逻辑单位可以简化存储子系统
3.块非常适合用于数据备份进而提供数据容错能力
在Hadoop2系列中,block块大小默认是128M,block块的大小可以通过hdfs-site.xml
当中的配置文件进行指定
<property>
<name>dfs.block.size</name>
<value>以字节为单位</value>
</property>
HDFS的命令行使用
ls
hdfs dfs -ls URI #类似于Linux的ls命令,显示文件列表
hdfs dfs -ls / #示例
lsr
hdfs dfs -lsr URI
#在整个目录下递归执行ls
mkdir
hdfs dfs [-p] -mkdir <paths>
#以<paths>中的URI作为参数,创建目录,使用-p参数可以递归创建目录
put
hdfs dfs -put <localsrc> ... <dst>
#将单个的源文件src或者多个源文件srcs从本地文件系统拷贝到目标文件系统中(<dst>对应的路径),也可以从标准输入中读取输入,写入目标文件系统中
get
hdfs dfs -get [-ignorecrc] [-crc] <src> <localhost>
rm
hdfs dfs -rm [-r] URI
#删除参数指定的文件,参数可以有多个,此命令只删除文件和非空目录
cp
hdfs dfs -cp URI <dest>
#-f 选项将覆盖目标,如果它已经存在
#-p 选项将保留文件属性(深度拷贝)
chown
hdfs dfs -chmod [-R] URI
#改变文件的所属用户和用户组;-R则对整个目录有效递归执行
HDFS的高级命令
查看配额信息:
hdfs dfs -count -q -h /...
文件数量限额:
hdfs dfsadmin -setQuota 2 文件名
#给该文件夹下面设置最多上传两个文件,发现只能上传一个文件
文件空间大小限额:
在设置空间配额时,设置的空间至少是block_size * 3
的大小
hdfs dfsadmin -setSpaceQuota 4k /...
#限额大小为4KB
清除空间大小限额:
hdfs dfsadmin -clrSpaceQuota ...
安全模式:
hdfs dfsadmin -safemode get #查看安全模式状态
hdfs dfsadmin -safemode enter #进入
hdfs dfsadmin -safemode leave #退出
HDFS写入过程
HDFS写文件流程:
- Client 发起文件上传请求,通过 RPC(远程过程调用Remote Procedure Call) 与 NameNode 建立通讯,NameNode 检查目标文件是否已存在,父目录是否存在,返回是否可以上传
- Client 请求第一个 block 该传输到哪些 DataNode 服务器上
- NameNode 根据配置文件中指定的备份数量及机架感知原理进行文件分配,返回可用的DataNode 的地址如: A,B,C
Hadoop 在设计时考虑到数据的安全与高效,数据文件默认在 HDFS 上存放三份,存储策略为本地一份,同机架内其它某一节点上一份,不同机架的某一节点上一份。 - 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 将 pipelineack 发送给 Client
- 当一个 block 传输完成之后,Client 再次请求 NameNode 上传第二个 block 到服务 1
HDFS读取过程
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的API操作
HDFS-HA高可用
如果想了解如何搭建Hadoop高可用模式可以参考我的博文:
如何手动搭建Hadoop-HA(高可用)模式?(内含报错和解决方法)