- 01 引言
- 02 HDFS概述
- 2.1 HDFS定义
- 2.2 HDFS优缺点
- 03 HDFS架构
- 3.1 NameNode管理者
- 3.2 DataNode执行者
- 3.3 Client客户端
- 3.4 Secondary NameNode辅助者
- 3.5 Block块
- 3.6 机架感知
- 04 HDFS读写流程
- 4.1 写流程
- 4.2 读流程
- 05 文末
由于接下来需要用到hdfs的技术,从本篇开始,有关hdfs的学习笔记都会记录到《HDFS专栏》专栏。
接下来,开始我们愉快的Hdfs学习之旅!
HDFS(Hadoop Distributed File System):它是一个文件系统,用于存储文件,通过目录树来定位;其次,它是分布式的,由很多服务联合起来实现其功能,集群中的服务器有各自的角色。
HDFS使用场景: 适合一次写入,多次读出的场景,且不支持文件的修改。适合用来做数据分析,并不适合用来做网盘应用。
2.2 HDFS优缺点HDFS优点:
- 高容错性: 数据自动保存多个副本,它通过增加副本的形式,提高容错性,当某一个副本丢失以后,它可以自动恢复;
- 适合处理大数据:它的数据规模能够处理数据规模达到
GB,TB,甚至PB级别的数据;文件规模能够处理百万规模以上的文件数量,数量相当之大; - 可构建在廉价机器上:通过多副本机制,提高可靠性。
HDFS缺点:
- 不适合低延迟数据访问:比如毫秒级的存储数据,是做不到的;
- 无法高效的对大量小文件进行存储:存储大量小文件的话,他会占用
NameNode大量的内存来存储文件目录块信息。这样是不可取的,因为NameNode的内存总是有限的;小文件存储的寻址时间会超过读取时间,它违反了HDFS的设计目标; - 不支持并发写入,文件随机修改:一个文件只能有一个写,不允许多个线程同时写。仅支持数据
append(追加),不支持文件的随机修改。
贴上hdfs官方的架构图: 根据架构图,可以看出
HDFS主要由如下几个部分组成:
- NameNode
- DataNode
- Client
- Secondary NameNode
- Block
下面讲解下。
3.1 NameNode管理者NameNode: 就是Master,他是一个主管,管理者。
它主要的作用:
- 管理
HDFS的名称空间; - 配置副本策略;
- 管理数据块(
Block)映射信息; - 处理客户端读写请求。
NameNode主要维护两个文件:
- FsImage:
FsImage是一个“镜像文件”。它保存了最新的元数据检查点,包含了整个HDFS文件系统的所有目录和文件的信息。对于文件来说包括了数据块描述信息、修改时间、访问时间等;对于目录来说包括修改时间、访问权限控制信息(目录所属用户,所在组)等; - EditLog:
EditLog主要是在NameNode已经启动情况下对HDFS进行的各种更新操作进行记录,HDFS客户端执行所有的写操作都会被记录到editlog中。
DataNode: 就是Slave,当NameNode下达命令,DataNode执行实际的操作。
它的主要作用:
- 存储实际的数据块,所以
DataNode节点需要较大的磁盘 - 执行数据块的读/写操作;
- 定期向
NameNode发送心跳,如果NameNode长时间没有接受到DataNode发送的心跳,NameNode就会认为该DataNode失效,将其剔除集群(心跳参数dfs.heartbeat.interval=3,默认3秒发送一次心跳); DataNode会定时上报自己负责的数据块列表。
Client:就是客户端。
它的主要作用:
- 文件切分,文件上传
HDFS的时候,Client将文件切分成一个一个的Block,然后进行上传; - 与
NameNode交互,获取文件的位置信息; - 与
Datanode交互,读取或者写入数据; Client提供一些命令来管理HDFS,比如NameNode格式化;Client可以通过一些命令来访问HDFS,比如对HDFS增删改查操作。
Secondary NameNode:并非NameNode的热备,当NameNode宕掉的时候,它并不能马上替换NameNode并提供服务。
它的作用:
- 镜像备份:备份
fsimage(fsimage是元数据发送检查点时写入文件); - 日志与镜像的定期合并:将
Namenode中edits日志和fsimage合并,防止如果Namenode节点故障,Namenode下次启动的时候,会把fsimage加载到内存中,应用edit log,edit log往往很大,导致操作往往很耗时;
block:HDFS中文件在物理上是分块存储(Block),块的大小可以通过配置参数(dfs.blocksize)来规定,默认大小在Hadoop2.x版本是128M,在Hadoop1.x版本中是64M。
默认大小设置为128M的原因:
- 如果寻址时间为
10ms,即查找到目标的bolck的时间为10ms; - 寻址时间为传输时间的
1%时,则为最佳状态。因此,传输时间=寻址时间/0.01=10ms/0.01=1000ms=1s - 而目前磁盘的传输速度普遍为
100MB/s - 因此block的大小为=1s*100MB/s=100M≈128M。
如何设置块大小:
- 块设置太小:会增加寻址时间,呈现一直在找块的开始位置;
- 块设置的太大:从磁盘传输数据的时间会明显大于定位这个块开始位置所需的时间,导致程序在处理这块数据时,会非常慢;
- HDFS块的大小设置,主要取决于磁盘传输速度。
举例:
- 如果数据的大小比
HDFS块大小还要小的话,那么块大小将等于数据的大小 - 如果文件大小是129MB,那么HDFS将创建2个block,一个block的大小是默认值,即128MB,另外一个block就只有1MB,而不是128MB
在大型Hadoop集群,为了在读写文件的时候改善网络传输,Namenode会选择给同一个机架或者最近的机架上的Datanode发送读写请求。NameNode通过维护每个DataNode的机架id来获取机架信息。
HDFS机架感知:就是基于机架信息选择Datanode的过程。
机架感知的作用:
- 提升数据的高可用和可靠性。
- 改善集群性能。
- 改善网络带宽。
下面来讲解HDFS的操作流程已加深对HDFS的架构理解。
4.1 写流程比如文件上传流程:
- 客户端发起写文件请求
hadoop fs -put; NameNode检查上传文件的命名空间是否存在(就是检测文件目录结构是否存在),创建者是否有权限进行操作,然后返回状态给客户端你可以上传数据;- 客户端按照分块配置大小将文件分块,然后请求
NameNode我要上传blk1,副本数是三个,这个文件一共分割了5块。 NameNode检测自己管理下的DateNodes是否满足要求,然后返回给客户端三台DateNode节点信息(存储策略是机架模式);Client端根据返回的DataNode信息选择一个离自己最近的一个DataNode节点,创建pipeLine(数据传输管道),DataNode1->DataNode2创建pipeLine,DataNode2->DataNode3创建pipeLine;DataNode3通过这一串管道传递给client数据传输管道已经建立完毕;client端创建Stream流(以packet为单位传输数据64kb)上传数据;DataNode1接受并保持源源不断的packet,然后把packet源源不断的传递给DataNode2,DataNode2也做相应的操作。DataNode也通过pipeLine发送ACK认证数据是否接收完毕。- 第一个数据块上传完毕后
client端开始上传第二个数据块。
写流程Java示例:
Configuration conf = new Configuration();
FileSystem fileSystem = FileSystem.get(conf);
// Check if the file already exists
Path path = new Path("/path/to/file.ext");
if (fileSystem.exists(path)) {
System.out.println("File " + dest + " already exists");
return;
}
// Create a new file and write data to it.
FSDataOutputStream out = fileSystem.create(path);
InputStream in = new BufferedInputStream(new FileInputStream(new File(source)));
byte[] b = new byte[1024];
int numBytes = 0;
while ((numBytes = in.read(b)) > 0) {
out.write(b, 0, numBytes);
}
// Close all the file descripters
in.close();
out.close();
fileSystem.close();
4.2 读流程
比如文件的获取流程:
client发起hadoop fs -get请求;NameNode检查该文件的信息,文件的分块信息和每个分块所对应哪个DateNode,以及备份信息和备份信息所在哪个DataNode;NameNode把这些信息返回给client端。(返回原则也是机架原则,根据网络拓扑将距离最近的DataNode排在前边返回);- 根据
NameNode的信息,请求各个文件块对应的DataNode节点获取文件数据; - 合并下载过来的数据块,形成一个完整的文件。
读流程Java示例:
Configuration conf = new Configuration();
FileSystem fileSystem = FileSystem.get(conf);
Path path = new Path("/path/to/file.ext");
if (!fileSystem.exists(path)) {
System.out.println("File does not exists");
return;
}
FSDataInputStream in = fileSystem.open(path);
int numBytes = 0;
while ((numBytes = in.read(b))> 0) {
System.out.prinln((char)numBytes));// code to manipulate the data which is read
}
in.close();
out.close();
fileSystem.close();
05 文末
本文是通过搜集资料并根据自己的理解整理的,如有疑问的童鞋欢迎留言,谢谢大家的阅读,本文完!
参考文献:
- https://www.cnblogs.com/laov/p/3434917.html
- https://www.hadoopdoc.com/hdfs/hdfs-architecture
