赞
踩
由于接下来需要用到hdfs
的技术,从本篇开始,有关hdfs
的学习笔记都会记录到《HDFS专栏》专栏。
接下来,开始我们愉快的Hdfs
学习之旅!
HDFS(Hadoop Distributed File System):它是一个文件系统,用于存储文件,通过目录树来定位;其次,它是分布式的,由很多服务联合起来实现其功能,集群中的服务器有各自的角色。
HDFS使用场景: 适合一次写入,多次读出的场景,且不支持文件的修改。适合用来做数据分析,并不适合用来做网盘应用。
HDFS优点:
GB
,TB
,甚至PB
级别的数据;文件规模能够处理百万规模以上的文件数量,数量相当之大;HDFS缺点:
NameNode
大量的内存来存储文件目录块信息。这样是不可取的,因为NameNode
的内存总是有限的;小文件存储的寻址时间会超过读取时间,它违反了HDFS
的设计目标;append
(追加),不支持文件的随机修改。贴上hdfs
官方的架构图:
根据架构图,可以看出HDFS
主要由如下几个部分组成:
下面讲解下。
NameNode: 就是Master
,他是一个主管,管理者。
它主要的作用:
HDFS
的名称空间;Block
)映射信息;NameNode
主要维护两个文件:
FsImage
是一个“镜像文件”。它保存了最新的元数据检查点,包含了整个HDFS
文件系统的所有目录和文件的信息。对于文件来说包括了数据块描述信息、修改时间、访问时间等;对于目录来说包括修改时间、访问权限控制信息(目录所属用户,所在组)等;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=1s100MB/s
如何设置块大小:
举例:
HDFS
块大小还要小的话,那么块大小将等于数据的大小在大型
Hadoop
集群,为了在读写文件的时候改善网络传输,Namenode
会选择给同一个机架或者最近的机架上的Datanode发送读写请求。NameNode
通过维护每个DataNode
的机架id
来获取机架信息。
HDFS
机架感知:就是基于机架信息选择Datanode
的过程。
机架感知的作用:
下面来讲解HDFS的操作流程已加深对HDFS的架构理解。
比如文件上传流程:
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();
比如文件的获取流程:
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();
本文是通过搜集资料并根据自己的理解整理的,如有疑问的童鞋欢迎留言,谢谢大家的阅读,本文完!
参考文献:
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。