HDFS 架构
大数据处理技术 - HDFS 的架构
基础架构
1、 NameNode
是一个中心服务器,单一节点(简化系统的设计和实现),负责管理文件系统的名字空间 namespace
以及客户端对文件的访问
2、 文件操作,namenode
是负责文件元数据的操作,datanode
负责处理文件内容的读写请求,跟文件内容相关的数据流不经过 Namenode
,只询问它跟哪个 dataNode
联系,否则 NameNode
会成为系统的瓶颈
3、 副本存放在哪些 Datanode
上由 NameNode
来控制,根据全局情况作出块放置决定,读取文件时 NameNode
尽量让用户先读取最近的副本(网络拓扑图),降低读取网络开销和读取延时
4、 NameNode
全权管理数据库的复制(永远保证有三个副本),它周期性的从集群中的每个 DataNode
接收心跳信合和状态报告,接收到心跳信号意味着 DataNode
节点工作正常,块状态报告包含了一个该 DataNode
上所有的数据列表
NameNode 与 Datanode 的总结概述
NameNode | Datanode |
---|---|
存储元数据 | 存储文件内容 |
元数据存储在 内存中 | 文件内容存储在硬盘上 |
保存文件、block、DataNode 之间的映射关系 | 维护了 block id 到 DataNode 本地文件之间的映射关系 |
文件划了几个 block 块,存在那些个 DataNode 上
文件的文件副本机制以及 block 块存储
所有的文件都是以 block
块的方式存放在 HDFS
文件系统当中,在 hadoop1 当中,文件的 block
块默认大小是 64M
,hadoop2 当中,文件的 block
块大小默认是 128M
,block
块的大小可以通过 hdfs-site.xml
当中的配置文件进行指定
<property> |
元数据信息 FSimage 以及 edits 和 secondaryNN 的作用
在 hadoop 当中,使用如下架构的时候
也就是 namenode
就一个的时候,所有的元数据信息都保存在了 FsImage
与 Eidts
文件当中,这两个文件就记录了所有的数据的元数据信息,元数据信息的保存目录配置在了 hdfs-site.xml
当中
<property> |
FSImage 与 edits 详解
客户端对 hdfs
进行写文件时会首先被记录在 edits
文件中。edits
修改时元数据也会更新。每次 hdfs
更新时 edits
先更新后客户端才会看到最新信息。
fsimage
: 是 namenode 中关于元数据的镜像,一般称为检查点。
一般开始时对 namenode 的操作都放在 edits 中,为什么不放在 fsimage 中呢?
因为 fsimage
是 namenode 的完整的镜像,内容很大,如果每次都加载到内存的话生成树状拓扑结构,这是非常耗内存和 CPU。
fsimage
内容包含了 namenode 管理下的所有 datanode 中文件及文件 block 及 block 所在的 datanode 的元数据信息。随着 edits 内容增大,就需要在一定时间点和 fsimage
合并。
合并过程见 SecondaryNameNode 如何辅助管理 FSImage 与 edits
FSimage 文件当中的文件信息查看
官方查看文档
https://hadoop.apache.org/docs/r2.6.0/hadoop-project-dist/hadoop-hdfs/HdfsImageViewer.html
使用命令 hdfs oiv
cd /export/servers/hadoop-2.6.0-cdh5.14.0/hadoopDatas/namenodeDatas/current |
(md5 校验文件,不是真正文件)
edits 当中的文件信息查看
官方查看文档
https://hadoop.apache.org/docs/r2.6.0/hadoop-project-dist/hadoop-hdfs/HdfsEditsViewer.html
查看命令 hdfs oev
cd /export/servers/hadoop-2.6.0-cdh5.14.0/hadoopDatas/dfs/nn/edits |
secondarynameNode 如何辅助管理 FSImage 与 Edits 文件
- 1:
secnonaryNN
通知NameNode
切换editlog
- 2:
secondaryNN
从NameNode
中获得FSImage
和editlog
(通过http
方式) - 3:
secondaryNN
将FSImage
载入内存,然后开始合并editlog
,合并之后成为新的fsimage
- 4:
secondaryNN
将新的fsimage
发回给NameNode
- 5:
NameNode
用新的fsimage
替换旧的fsimage
完成合并的是 secondarynamenode
,会请求 namenode 停止使用 edits, 暂时将新写操作放入一个新的文件中 edits.new
。secondarynamenode
从 namenode 中通过 http get 获得 edits,因为要和 fsimage 合并,所以也是通过 http get 的方式把 fsimage 加载到内存,然后逐一执行具体对文件系统的操作,与 fsimage 合并,生成新的 fsimage,然后把 fsimage 发送给 namenode,通过 http post 的方式。namenode 从 secondarynamenode 获得了 fsimage 后会把原有的 fsimage 替换为新的 fsimage, 把 edits.new 变成 edits。同时会更新 fstime。
hadoop 进入安全模式时需要管理员使用 dfsadmin 的 save namespace 来创建新的检查点。
secondarynamenode 在合并 edits 和 fsimage 时需要消耗的内存和 namenode 差不多,所以一般把 namenode 和 secondarynamenode 放在不同的机器上。fs.checkpoint.period
: 默认是一个小时(3600s
)fs.checkpoint.size
: edits 达到一定大小时也会触发合并(默认 64MB
)
HDFS 的文件写入过程
详细步骤解析:
- 1、 client 发起文件上传请求,通过 RPC 与 NameNode 建立通讯,NameNode 检查目标文件是否已存在,父目录是否存在,返回是否可以上传;
- 2、 client 请求第一个 block 该传输到哪些 DataNode 服务器上;
- 3、 NameNode 根据配置文件中指定的备份数量及机架感知原理进行文件分配,返回可用的 DataNode 的地址如:A,B,C;注:Hadoop 在设计时考虑到数据的安全与高效,数据文件默认在 HDFS 上存放三份,存储策略为本地一份,同机架内其它某一节点上一份,不同机架的某一节点上一份。
- 4、 client 请求 3 台 DataNode 中的一台 A 上传数据(本质上是一个 RPC 调用,建立 pipeline),A 收到请求会继续调用 B,然后 B 调用 C,将整个 pipeline 建立完成,后逐级返回 client;
- 5、 client 开始往 A 上传第一个 block(先从磁盘读取数据放到一个本地内存缓存),以 packet 为单位(默认 64K),A 收到一个 packet 就会传给 B,B 传给 C;A 每传一个 packet 会放入一个应答队列等待应答。
- 6、 数据被分割成一个个 packet 数据包在 pipeline 上依次传输,在 pipeline 反方向上,逐个发送 ack(命令正确应答),最终由 pipeline 中第一个 DataNode 节点 A 将 pipelineack 发送给 client;
- 7、 当一个 block 传输完成之后,client 再次请求 NameNode 上传第二个 block 到服务器。
HDFS 的文件读取过程
详细步骤解析
- 1、 Client 向 NameNode 发起 RPC 请求,来确定请求文件 block 所在的位置;
- 2、NameNode 会视情况返回文件的部分或者全部 block 列表,对于每个 block,NameNode 都会返回含有该 block 副本的 DataNode 地址; 这些返回的 DN 地址,会按照集群拓扑结构得出 DataNode 与客户端的距离,然后进行排序,排序两个规则:网络拓扑结构中距离 Client 近的排靠前;心跳机制中超时汇报的 DN 状态为 TALE,这样的排靠后;
- 3、 Client 选取排序靠前的 DataNode 来读取 block,如果客户端本身就是 DataNode, 那么将从本地直接获取数据 (短路读取特性);
- 4、 底层上本质是建立
Socket Stream
(FSDataInputStream
),重复的调用父类DataInputStream
的 read 方法,直到这个块上的数据读取完毕; - 5、 当读完列表的 block 后,若文件读取还没有结束,客户端会继续向 NameNode 获取下一批的 block 列表;
- 6、 读取完一个 block 都会进行 checksum 验证,如果读取 DataNode 时出现错误,客户端会通知 NameNode,然后再从下一个拥有该 block 副本的 DataNode 继续读。
- 7、 read 方法是并行的读取 block 信息,不是一块一块的读取;NameNode 只是返回 Client 请求包含块的 DataNode 地址,并不是返回请求块的数据;
- 8、 最终读取来所有的 block 会合并成一个完整的最终文件。