好程序员大数据学习路线分享
分布式文件系统HDFS,设计目标:
1
、存储量大
2
、自动快速检测应对硬件错误
3
、流式访问数据
4
、移动计算比移动数据本身更划算
5
、简单一致性模型
6
、异构平台可移植
特点
优点:
-
高可靠性:Hadoop
按位存储和处理数据的能力强
-
高扩展性:hadoop
是在可用的计算机集簇间分配数据并完成计算任务的,这些集簇可以方便地扩展到数以千计的节点中
-
高效性:hadoop
能够在节点之间动态地移动数据,并保证各个节点的动态平衡,因此处理速度非常快
-
高容错性:hadoop
能够自动保存数据的多个副本,并且能够自动将失败的任务重新分配。
缺点:
- 不适合低延迟数据访问
-
无法高效存储大量小文件(每个文件存储都有属于自己的索引,
元数据庞大就不高效)
- 不支持多用户写入及任意修改文件(可以删除以及追加,只是不能修改文件中某处的数据)
重要特性:
-
文件在物理上是分块存储,块的大小可以通过配置参数(dfs.blocksize)
来规定,
默认
2.x
版本之后是
128M
,老版本是64M
- HDFS
会给哭护短提供一个统一的
抽象目录树
,客户端通过路径来访问文件,
刑辱:
hdfs://namenode:port/dir-a/dir-b/dir-c/file.data
-
目录结构及文件分块信息(
元数据
)
的管理由namenode
承担—namenode
是
HDFS
集群主节点,负责维护整个
hdfs
文件系统的目录树,以及每一个路径(文件)所对应的
block
块信息(
block
的
id
以及所在
datanode
服务器)
-
文件的各个block
的存储管理由
datanode
承担—datanode
是
HDFS
集群从节点,每一个
block
都可以在多个
datanode
上存储多个副本(副本参数设置
dfs.replication)
- HDFS
是设计成适应一次写入,
多次读出的场景,
且不支持文件的修改
-
管理文件系统的命名空间(
元数据<metadata>:包含文件名称、大小、所属人、地址)
- 规定客户端访问文件规则
三个服务
Namenode
任务清单
a)
文件大小是否已经超载(
超过集群的负载)
b)
是否已经存在相同的文件
c) 是否具有创建该文件的权限
- 对文件执行命令,关闭,打开文件或者打开路径等操作
-
所有的数据节点发送心跳给NameNode
,他需要确保数据节点
DataNode
是否在线,一个数据块报告包含所有这个数据节点上的所有
block
的状况
-
首先将fsimage(镜像)
载入内存,并读取执行日志editlog
的各项操作
-
一旦在内存中建立文件系统元数据映射,则创建一个新的fsimage
文件(这个过程不需要
secondaryNamenode
)和一个空的
editlog
-
在安全模式下,各个datanode
会向
namenode
发送块列表的最新情况
-
此刻namenode
运行在安全模式。即
NameNode
的文件系统对于客户端来说是只读
- NameNode
开始监听
RPC
和
HTTP
请求
启动过程
RPC:Remote Procedure Call Protocol---远程过程通过协议
它是一种通过网络从远程计算机程序上请求服务,而不需要了解底层网络技术的协议
-
系统中数据块的位置并不是由namenode
维护的
,
而是以块列表形式存储在
datanode
中
-
在系统的正常操作期间,namenode
会在内存中保留所有块信息的映射信息
- fsimage:元数据镜像文件(保存文件系统的目录树)
- edit.log:
元数据操作日志(
针对目录树的修改操作)
两个重要文件
元数据镜像
a) 内存中保存一份最新的
b)
内存中镜像=fsimage+edits
SecondaryNamenode
工作任务
定期合并fsimage
与
edits
c) Edits
文件过大将导致
NamenNode
重启速度缓慢
d) SecondaryNameNode
负责定期合并他们
Datanode
hdfs
的写过程
写过程语言Description
:
- Client
通过调用
FileSystem
的
get
方法与
namenode
进程建立通道进行通信,然后调用
create
方法来请求创建文件。
- FileSystem
通过对
namenode
发出远程请求,在
namenode
里面创建一个新的文件,但此时并不关联任何的块。
NameNode
进行很多检查来保证不存在要创建的文件已经存在文件系统中,同时检查是否有相应的权限来创建文件。如果这些检查完了,
nameNameNode
将这个新文件的嘻嘻记录下来,然后
FileSystem
返回一个
DFSOutputStream
给客户端用来写入数据。和读的情形一样,
FSDataOutputStream
将包装一个
DFSOutputStream
用于和
DataNode
及
NameNode
通信。而一旦文件创建失败,客户端会受到一个
IOException,标识文件创建失败,停止后续任务。
-
客户端开始写数。FSDataOutputStream
把要写入的数据分成块打成包的形式,将其写入到
DFSOutputStream
对象的中间队列中。其中的数据由
Datastreamer
来读取。DataStreamer
的职责是让NameNode
分配新的块—
找出合适的DataNode
来存储作为备份而复制的数据。
- FSDataOutputStream
维护了一个内部关于
packets
的队列,里面存放等待被
DataNode
确认无误的
packets
的信息。这个队列被称为等待队列,一个
packet
的信息被移出本队列当且仅当
packet
被所有节点都确认无误。
-
当完成数据写入之后客户端调用流的close
方法,再通知
NameNode
完成写入之前,这个方法将
flush
残留的
packets
,并等待确认信息。
NameNode
已经知道文件由哪些块组成,所以在返回成功前只需要等待数据块进行最小复制。
Write
API
:
1
.
从本地系统上传到hdfs
Configuration hdfsConf = new Configuration();//
创建一个hdfs
的环境变量
String namenodeURI=”hdfs://hadoop001:8020”;//namenode的统一资源定位符
String username=”root”;//
访问指定用户的hdfs
FileSystem hdfs = FileSystem.get(new URI(namenodeURI),hdfsConf,username);//
创建一个hdfs
的文件系统对象
FileSystem local = FileSystem.getLocal(new Configuration());//创建一个本地的文件系统对象
hdfs.copyFromLocalFile(new Path(localPath),new Path(hdfsPath));
2.
在hdfs
上创建文件并直接给定文件的内容
FSDateOutputStream out = hdfs.create(new Path(hdfsPath));
out.write(fileContent.getBytes());
out.close();
hdfs
的读过程
读过程语言Description
:
-
客户端或者用户通过调用FileSystem
对象的
open
方法打开需要读取的文件,这对
HDFS
来说是常见一个分布式文件系统的一个读取实例。
- FileSystem
通过远程协议调用
NameNode
确定文件的前几个
Block
的位置。对于每一个
Block
,
Namenode
返回含有那个Block
的“元数据”,即文件基本信息;接下来,
DataNode
按照上文定义的距离来进行排序,如果Client
本身就是一个
DataNode
优先从本地
DataNode
读物数据。
HDFS
实例完成以上工作后,返回一个
FSDataInputStream
给客户端,让其从
FSDataInputStream
中读取数据。
FSDataInputStream
接着包装一个
DFSInputStream
用来管理
DataNode
和
NameNode
的
I/O
。
- NameNode
向客户端返回一个包含数据信息的地址,客户端格努诋毁创建一个
FSDataInputStream
开始对数据进行读取。
- FSDataInputStream
根据开始存放的前几个
Blocks
的
DataNode
的地址,连接到最近的
DataNode
上对数据开始从头读取。客户端反复调用
read()
方法,以流式方式从DataNode
读取数据
-
当读到Block
的结尾的时候,
FSDataInputStream
会关闭当前
DataNode
的地址,然后查找能够读取下一个Block
的最好的
DataNode
。这些操作对客户端是透明的,客户端感觉到的是连续的流,也就是说读取的时候就开始查找下一个块所在的地址。
-
读取完成调用close()
方法,关闭FSDataInputStream
。
Read
API
:
1
.
从h
dfs
上下载文件到本地
Configuration hdfsConf = new Configuration();//
创建一个hdfs
的环境变量
String namenodeURI=”hdfs://hadoop001:8020”;//namenode的统一资源定位符
String username=”root”;//
访问指定用户的hdfs
FileSystem hdfs = FileSystem.get(new URI(namenodeURI),hdfsConf,username);//
创建一个hdfs
的文件系统对象
FileSystem local = FileSystem.getLocal(new Configuration());//创建一个本地的文件系统对象
hdfs.copyToLocalFile(new Path(hdfsPath),new Path(localPath));
3.
在hdfs
上读取给定文件的内容
Path path = new Path(hdfsFilePath);//文件路径
FSDataInputStream in = hdfs.open(path);//获取文件输入流
FileStatus status = hdfs.getFileStatus(path);//获取文件的元数据信息
//获取文件元数据中的文件大小
byte[] bytes = new byte[Integer.pareInt(String.valueOf(status.getLen()))];
//将输入流中的全部内容一次性读取出来
in.readFully(0,bytes);
System.out.println(new String(bytes));//将读取的文件打印输出
in.close();
hdfs
的整体过程

来自 “ ITPUB博客 ” ,链接:https://blog.itpub.net/69913892/viewspace-2654618/
,如需转载,请注明出处,否则将追究法律责任。