HDFS概述
HDFS是Hadoop 分布式文件系统,可以运行在通用硬件上、提供流式数据操作、能够处理超大文件的分布式文件系统。HDFS具有高度容错、高吞吐量、容易扩展、高可靠性等特征。
HDFS是一个主/从体系结构的分布式系统,拥有1个Namenode和多个Datanodes,用户可以通过HDFS客户端同Namenode和Datanodes交互以访问文件系统。Namenode是HDFS的Master节点, 负责管理文件系统的命名空间,以及数据块到具体Datanode节点的映射等信息
。Datanode一般是一个节点一个, 负责管理它所在节点上的存储。
一个文件被分成一个或多个数据块, 这些块存储在一组Datanode上
, Datanode以本地文件的形式保存这些数据块以及数据块的校验信息。
高延迟问题
- 使用缓存或多master设计,以减轻client的数据压力。
存储小文件问题
- 归档小文件,将小文件归档起来管理(HBase就是基于此)。如果想找回原来小文件内容,必须知道小文件与归档文件的映射关系。
- 横向扩展,一个Hadoop集群管理小文件有限,把几个Hadoop集群拖在一个虚拟服务器里面,形成一个大的Hadoop集群。
- 多Master设计。
HDFS基本概念
HDFS文件以数据块形式存储, 数据块是HDFS文件处理(读或者写)的最小单元
。 由于HDFS文件往往较大,同时为了最小化寻址开销,所以HDFS数据块也更大
,默认是128MB。数据块以文件形式存储在Datanode的磁盘上。
读操作中,HDFS客户端会首先 到Namenode查找HDFS文件包含的数据块的位置信息
,然后根据尾值信息从Datanode读取数据。
写操作中,HDFS客户端也会首先 从Namenode申请新的数据块
,然后根据新申请数据块的位置信息建立数据流管道写数据。
Namenode 管理着文件系统的命名空间(namespace),包括文件系统目录树、文件/目录信息以及文件的数据块索引,这些信息以两个文件的形式 永久保存
在Namenode的本地磁盘,即 命名空间镜像文件和编辑日志文件
。同时还保存着 数据块与数据节点的对应关系
,这部分数据不保存在本地磁盘,而是在Namenode 启动时动态构建
。HDFS客户端会通过名字节点获取上述信息,之后读写文件。
Namenode是HDFS的单一故障点,Hadoop2.X引入HA。同一个集群配置两个Namenode, Active-Namenode的内存元数据与Standby-Namenode完全同步
。
因为Namenode中保存了数据块与数据节点的对应关系。如果 集群文件数量过多,Namenode的内存将成为限制系统横向扩展的瓶颈
。为了解决这个问题,Hadoop2.X引入 联邦HDFS机制
(Hadoop Federation)。其允许添加Namenode以实现命名空间的扩展, 每个Namenode管理文件系统命名空间的一部分,是一个独立的名空间卷。卷之间相互独立,两两之间不通信,一个Namenode失效了也不会影响其他Namenode所维护的命名空间的可用性
。
Datanode会根据HDFS客户端请求或者Namenode调度将新的数据块写入本地存储,或者读出本地存储上保存的数据块。
作为从节点,Datanode会不断地向Namenode发送心跳、数据块汇报、缓存汇报,Namenode会通过心跳、数据块汇报、缓存汇报的 响应
向Datanode发送指令,Datanode会执行这些指令。
由于HDFS作为一个分布式文件系统,某些流程非常复杂,常常涉及Datanode、Namenode、Client三者之间的配合以及相互调用。为了降低耦合,HDFS将这些节点间的调用抽象成不同的接口。
Hadoop RPC接口:HDFS基于Hadoop RPC框架实现的接口
流式接口: HDFS基于TCP或者HTTP实现的接口
HDFS主要流程
浅看,未深入源码
异常情况:
读数据时,存储这个数据块的Datanode出现异常,无法读取数据。DFSInputStream会 切换到另一个保存了这个数据块的数据节点读取数据
。
数据块的应答包中不仅包含了数据,还包含校验值, HDFS客户端收到数据应答包时,会校验数据
。如果出现校验错误,也就是数据节点上的这个数据块副本出现了损坏,Client会 向Namenode汇报这个损坏的数据块副本
,同时DFSInputStream会 尝试从其他的数据节点读取这个数据块
。
对于Datanode, 当Datanode成功地接收一个新的数据块时
,Datanode会向Namenode汇报, Namenode会更新内存中的数据块与数据节点的对应关系
异常情况:
客户端写文件是, 数据流管道中的Datanode故障
,有如下故障恢复操作:
输出流中缓存的没有确认的packet会重新加入发送队列
。输出流会为数据块申请一块新的时间戳,用新时间戳重新建立数据流管道
。这保证故障Datanode上的数据块的时间戳会过期
,故障恢复之后,由于数据块的时间戳与Namenode元数据中的不匹配而被删除,保证了集群中所有数据块的正确性。故障Datanode点会从Datanode列表中删除,通知Namenode分配新的Datanode到数据流管道中
。接下来输出流会将新分配的Datanode添加到数据流管道中,并使用新的时间戳重新建立数据流管道。由于新添加的Datanode上并没有存储这个新的数据块,HDFS客户端会通知数据流管道中的一个Datanode复制这个数据块到新的Datanode上
。- 接下来以Datanode列表中的第一个Datanode作为”主节点”,其他Datanode作为”副本节点”。
数据流管道重新建立之后,输出流会更新Namenode中的元数据
。故障恢复完成,客户端可以完成后续的写操作。
追加写指打开一个已有文件并执行追加写操作,和写流程很类似,只不过在初始建立数据流管道时有些不同。
- 打开已有的HDFS文件,获取文件最后一个数据块的位置信息,如果数据块写满则返回null。创建到这个数据块的输出流对象DFSOutputStream,
获取文件租约
。 - 判断最后一个数据块是否写满,
- 如果没有写满,根据该数据块的位置信息建立到该数据块的数据流管道;
- 如果写满了,向Namenode申请一个新的数据块之后建立数据流管道。
- 通过数据流管道写入数据,和上面写流程类似。
- 关闭输入流,提交文件。同上
Datanode启动后与Namenode的交互主要包括三个部分:握手;注册;快汇报以及缓存汇报
Datanode启动过程
- Datanode启动时会首先获取Namenode的版本号以及存储信息,并比较,确保Datanode和Namenode版本号一致。
- Namenode收到注册请求后,判断当前Datanode的配置是否属于这个集群,版本号是否一致。
- 注册成功后,Datanode将本地存储的所有数据块以及缓存的数据块上报到Namenode,Namenode会利用这些信息重新建立内存中数据块与Datanode之间的对应关系。
Datanode工作过程
- Datanode成功启动后,需要定期向Namenode发送心跳,让Namenode知道其仍处于活动状态。Namenode会在Datanode的心跳响应中携带指令,知道Datanode进行数据块复制、删除以及恢复等操作。
-
Datanode成功添加一个新的数据块或者删除了一个已有的数据块时,向Namenode汇报,Namenode更新数据块与Datanode的对应关系。
-
Active Namenode 和 Standby Namenode 是实时同步的。
- 为了使Standby节点和Active节点状态能够同步一致,要求两个Namenode的命名空间一致并且数据块与Datanode之间的对应关系一致。
- 命名空间一致:两个节点都要与一组独立运行的节点(JournalNodes,JNS)通信,当Acvive 执行了修改命名空间的操作时,它会
定期
将执行的操作记录在editlog
中,并写入JNS的多数节点中
。Standby 会一直监听JNS上editlog的变化,如果有改动,就会读取editlog并与当前的命名空间合并。 - 当发生了错误切换,Standby节点会先保证已经从JNS上读取了
所有的
editlog并与命名空间合并,然后才切换到Active状态。 - 数据块与Datanode对应关系的一致性:要求HDFS集群中所有的Datanode
同时向这两个Namenode发送心跳以及快汇报信息
。这样就完全同步了,也就可以实现热备
。 - 自动Failover机制:
- Zookeeper集群
- ZKFailoverController:实时监控Namenode的HA状态,如果Active不可服务,那么会其会自动触发主备切换操作。
Hadoop RPC
RPC(Remote Procedure CallProtocol,远程过程调用协议),允许本地程序像调用本地方法一样调用远程机器上应用程序提供的服务。
Namenode
Datanode
《Hadoop 2.X HDFS源码剖析》
Original: https://www.cnblogs.com/ogleede/p/16536953.html
Author: 茶倌
Title: 《HDFS源码剖析》–初品ing
原创文章受到原创版权保护。转载请注明出处:https://www.johngo689.com/586369/
转载文章受原作者版权保护。转载请注明原作者出处!