HDFS小节
HDFS产生背景
随着数据量越来越大,在一个操作系统存不下所有的数据,那么就分配到更多的操作系统管理的磁盘中,但是不方便管理和维护,迫切需要一种系统来管理多台机器上的文件,这就是分布式文件管理系统。HDFS只是分布式文件管理系统中的一种
HDFS定义
-
HDFS(Hadoop Distributed File System),它是一个文件系统,用于存储文件,通过目录数来定位文件;其次,他是分布式的,有很多服务器联合起来实现其功能,集群中的服务器有各自的角色
-
HDFS的使用场景(特点):适合一次写入,多次读出的场景,且不支持文件的修改,适合用来做数据分析,并不适合用来做网盘应用
HDFS优缺点
- 优点
- 高容错性
- 数据自动保存多个副本,它通过增加副本的形式,来提高容错性
- 某一个副本丢失之后,它可以自动恢复
- 适合处理大数据
- 数据规模:能够处理规模大到GB,TB,甚至PB级别的数据;
- 文件规模:能够处理百万规模以上的文件数量,数量相当大。
- 可构建在廉价机器上,通过多副本机制,提高可靠性。
- 高容错性
- 缺点
- 不适合低延时数据访问,比如毫秒级别的存储数据,是做不到的
- 无法高效的对大量小文件进行储存
- 储存大量小文件的话,会占用大量的内存来存储文件目录和块信息。这样是不可取的,因为namenode的内存是有限的
- 小文件储存的寻址时间会超过读取时间,违反了HDFS的实际目标
- 不支持并发写入,文件随机修改
- 一个文件只能有一个写,不允许多个线程同时写;
- 仅支持数据append(追加),不支持文件的随机修改
HDFS组成架构
- namenode(nn):就是Master,他是一个主管管理者
- 管理HDFS的名称空间;
- 配置副本策略;
- 管理数据块(block)映射信息;
- 处理客户端的读写请求
- datanode(dn):就是slave,namenode下达命令,datanode执行实际的操作
- 存储实际的数据块
- 执行数据块的读写操作
- client:就是客户端
- 文件切分。文件上传HDFS的时候,client将文件切分成一个一个block,然后进行上传;
- 与namenode交互,获取文件的位置信息;
- 与datanode交互,读取或者写入数据;
- client提供一些命令来管理HDFS,比如namenode格式化;
- client可以通过一些命令来访问HDFS,比如HDFS增删改查操作。
- secondary namenode(2nn):并非namenode的热备。当namenode挂掉的时候,他不能马上替换namenode并提供服务。
- 辅助namenode,分担其工作量,比如定期合并fsimage和edits,并推送给namenode;
HDFS文件块大小
HDFS中文件在物理上是分块存储,块的大小可以通过配置参数来规定,默认大小在hadoop2.x中是128M,老版本中是64M。
HDFS块的大小不能设置太小,也不能设置太大?
- HDFS的块设置的太小,会增加namenode的寻址时间,程序会一直在找块的开始位置
- 如果块设置的太大,从磁盘传输数据的时间会明显大于定位这个块开始位置所需的时间。导致程序在处理这块数据时,会非常慢。(会增加mapreduce的执行效率)
总结:HDFS块的大小设置主要取决于磁盘传输速率。
HDFS两种命令bin/hdfs dfs与bin/hadoop fs
在bin目录下hdfs与hadoop是两个用来执行java代码的脚本文件,dfs与fs分别是两个脚本的参数
hdfs脚本文件中输入dfs执行的是FsShell类
hadoop脚本文件中输入fs执行的同样是FsShell类
二者的本质都是一样的
HDFS的数据流
HDFS的写数据流程
-
首先我们有一个本地文件:文件大小假设200M;
-
如果将这个File上传到HDFS首先需要一个客户端(client):它来负责上传到HDFS。
- client中有一个类:DistributedFileSystem(整个集群的抽象封装)
-
client向nn发起一个申请上传的请求,nn向client响应可否上传
- 相同路径有没有同样的文件
- 是否有上传的权限
-
client获取nn通过的响应后,会将这个file分块儿(此时只是逻辑切分,并没有真的切分),然后client会开启FSDataOutputStream(输出流)
-
此时并没有开始写入dn,client会再次向nn发起请求:此时的请求是上传第一个块儿。nn会返回client一个dn的List
- list 设置集群副本数是几,就返回几个dn
- 返回的dn顺序:第一个是离client最近的一个dn1;之后的dn(2…n)是根据第一个dn1筛选出来的
-
client在获取到dn的list之后会向dn1发起建立通道的请求(数据通道),然后顺次dn1向dn2建立通道请求,之后同理,当最后一个dn获取请求后会向之前的dn应答成功,然后顺次向前应答,一直到dn1向client应答成功
-
client收到成功应答的时候,代表通道(串联)已经建立完毕。此时client就开始传输数据(packet队列)
- 当dn1收到packet队列之后,一边往本地落盘,一边将packet队列发送给dn2,之后同理
- 当最后一个dn落盘成功,会向前一个成功应答,前一个收到成功应答并且自身也落盘成功,继续以此向前应答到client
-
传输完毕之后第一块数据就同时存在与集群的dn上面,然后就同理开始传输第二块直至结束
-
文件传输完毕之后,client会关闭输出流,将数据传输完毕告诉nn,nn收到消息之后,会保存文件的元数据
注意:
1.每个块的dn的选择是完全独立的过程,也就是说同一个文件,它的两块有可能不在同一个dn上
2.HDFS的最小存储单位是块
3.假设上传失败了有几种可能情况:
(1).在建立通道的过程中失败,会抛出异常
(2).在传输过程中失败分两种情况
(2.1).在传输第一个dn过程中失败,同样会上传失败
(2.2).第一个传输dn成功,之后传输过程失败,上传仍然可以继续进行的,而且会返回成功讯号;原因是第一个上传成功,如果副本数大于1会触发自动备份
HDFS的读数据流程
-
同样读取流程会有一个client
- client中有一个类:DistributedFileSystem(整个集群的抽象封装)
-
client向nn发起一个申请读取的请求,nn向client响应可否读取
- 查看文件是否存在
- 是否有读取的权限
-
然后client会开启FSDataInputStream(输入流)
-
然后client向nn请求下载第一个块儿,nn收到client的请求会返回多个dn的list
-
此时向dn1请求建立通道,与写入不同的是如果dn1建立成功后dn1会立即向client应答成功,然后进行数据传输,如果dn1建立失败才会向后请求下一个,之后同理
-
第一个块传输完毕后第二个块继续执行直至结束
-
文件读取完毕后nn会告知client数据传输完毕,同理client会关闭输入流