Hdfs源码剖析--系列一

Hdfs简介

HDFS(Hadoop分布式文件系统)是运行在通用硬件上的分布式文件系统。HDFS提供了一个高度容错性和高吞吐量的海量数据存储解决方案。HDIFS已经在各种大型在线服务和 大型存储系统中得到广泛应用,已经成为各大网站等在线服务公司的海量存储事实标准,多 年来为网站客户提供了可靠、高效的服务。 -- "Hadoop 2.X HDFS源码剖析"第一章

简介

Hdfs使用场景:一次写入,多次读取,适合数据分析,不适合多次修改

HDFS(Hadoop Distributed File System)是一个开源系统,可以满足大文件处理的需求和流式数据的访问,可进行文件存储与传递,并且允许文件通过网络在多台主机上进行共享。HDFS文件系统主要分为两部分:NameNode、SecondaryNameNode(StandByNameNode)和DataNode。

HDFS的主要特点包括:

  1. 存取超大文件;
  2. 流式数据访问,即数据批量读取;
  3. 检测和快速应对硬件故障(高可用);
  4. 简单一致模型,即为了降低系统复杂度,对文件采用一次性多次读写的逻辑设计,即文件一旦写入、关闭,就再也不能修改-----(追加式写入);
  5. 程序采用数据就近原则分配节点执行(选择最近的节点副本数据返回给读文件的客户端);
  6. 高容错性:数据自动保存多个副本,副本丢失后自动恢复。

架构

HDFS采用主从架构进行管理,一个HDFS集群具有一个NameNode,一个SecondaryNode(StandByNameNode),至少一个DataNode,这些节点分别承担Master和Worker的任务。

NameNode

相当于HDFS的核心大脑。它用于存储HDFS的元数据(数据的数据,包括文件目录、文件名、文件属性等)、管理文件系统的命名空间以及保存整个文件系统的空间命名镜像(也称文件系统镜像FSImage),也就是说Namenode负责保存整个hdfs系统的目录树和存放在目录树的文件信息以及保存有空间命名镜像的编辑日志(EditLogs),客户端请求写入数据或者更改移动复制文件是,NameNode只对元数据操作记录而不对数据块操作记录,从NameNode中可以获得每个文件每个块所在的DataNode,但是这些信息不会永久存储,NameNode会在每次系统启动时动态重建这些信息。

java 复制代码
       Configuration configuration =new Configuration();
       FileSystem fileSystem=FileSystem.get(configuration);

SecondaryNode

由于整个文件系统比较庞大,读写数据比较多,因此空间命名镜像会越变越大,频繁对其进行操作会使系统运行变慢。于是HDFS将每一次对数据节点的操作都记录在NameNode的空间命名镜像的编辑日志(editLog)里,SecondaryNode负责定期合并FSImage和编辑日志(editLog)。SecondaryNode通常运行在另一台机器上,因为合并操作需要耗费大量的CPU时间以及和NameNode相当的内存,并且是定时合并,所以它的据落一定后于NameNode;当NameNode完全崩溃时,会出现数据丢失。通常解决方法是拷贝NFS中的备份元数据到SecondaryNode,将其作为新的主NameNode

markdown 复制代码
> Hadoop 2.x才出现,从以上描述中可以看出:SecondaryNode并不能被用作NameNode,只是,在活动NameNode故障之后,替代原有NameNode成为新的活动NameNode

DataNode

DataNode是HDFS主从架构的从角色、文件系统的工作节点、存储文件数据块的节点。在NameNode的命令下进行I/O任务、存储和提取块,响应客户端的一系列数据操作,并且DataNode会周期性地向NameNode汇报自身存储的数据块信息,更新NameNode中的元数据信息,接受NameNode的指令,完成对存储数据块的操作

客户端

HDFS提供了多种客户端接口供应用程序以及用户使用,包括命令行接口、浏览器接口 以及代码API接口。用户通过这些接口可以很方便地使用HDFS,而不需要考虑HDFS的实 现细节。

Hdfs主要流程

Hdfs写数据

  • 创建文件

写数据的第一步是,客户端会先调用DistributedFileSystem.createor()方法创建一个空文件,NameNode在文件系统指定目录树下添加一个文件,并记录操作到editLog中,该方法最终会返回DFSOutput Stream对象,用于写数据

  • 初始化数据流管道

第一步只是创建了一个空文件,接下来需要再调用ClientProtocol.addBlock()方法,向NameNode申请创建数据块,并返回LocatedBlock对象,保存了申请的数据块详细地址,DFSOutput Stream就可以创建数据流管道用于写数据了

  • 写数据

创建数据流管道后,开始写数据,首先需要写入的数据会被缓存在数据流中,然后在流中被切分成一个个数据包,然后依次发送给多个节点(多副本),当所有节点都返回数据写入成功的的确认消息后(逆序通过数据流返回写入流管道,数据流管道需要确认是否写成功),该数据包就会被删除,接着写入下一个数据包;当一个数据块被写满后,继续调用addBlock()申请新的block,然后重复上面的写入过程

  • 关闭写入

当完成数据写入后,主动关闭写入流管道,然后上报NameNode此次写入的数据块信息

Hdfs写入故障

如果客户端在写文件时,数据流管道中的数据节点出现故障,则输出流会进行如下操作 来进行故障恢复。

  1. 数据流管道中没有被确认写成功的数据包会重新进入数据流管道发送流程
  2. 将故障节点从数据流管道中删除,并请求NameNode重新申请新DataNode,并使用新的时间戳创建数据流管道,由于新的DataNode缺少之前的数据,因此写入新DataNode时,需要复制数据,来保证数据的完整性
  3. 创建新数据流管道时会初始化一个新的时间戳,然后使用它创建数据流管道,因此故障节点的数据时间戳就不会和NameNode元数据一致,那么故障节点的数据就会过期,保证了数据的准确性
  4. 建立新的数据流管道,完成数据复制后,客户端会向NameNode更新元数据

Hdfs追加写数据

  1. 打开一个已经存在的hdfs文件,获取这个文件的最后一个数据块位置
  2. 如果该文件的最后一个数据块已经写满,则会重新申请一个数据块,建立写入数据流管道写入数据,如果没有写满,则直接建立数据流管道写入数据,这一步和hdfs写数据的流程一致
  3. 写入完成后会关闭数据流管道,并向NameNode提交该文件的所有数据块信息

DataNode启动/心跳和执行NameNode命令


如上图所示,DataNode启动主要包含三个阶段:握手,注册,块信息上报:

  1. 启动后DataNode会获取NameNode的版本/存储等信息,确保自己和NameNode是一致的
  2. 确认一致后DataNode会向NameNode发起注册请求,NameNode收到注册请求后会确认当前的DataNode和自己处于同一个集群,以及版本/存储信息等一致
  3. 完成注册后,DataNode将本地存储的所有数据块及位置信息上报到NameNode,NameNode根据这些信息更新自己的元数据信息
  4. DataNode完成以上的操作后,就成功启动并在集群注册了,下来他就需要定期向NameNode发送心跳信息,让NameNode知道自己可以对外提供服务,而NameNode会在心跳响应的请求中携带命令,指导DataNode执行数据复制/删除/恢复等操作

HA流程

在Hadoop 2.x之前,NameNode在Hdfs中以单节点的形式存在,而一旦它故障,整个Hdfs集群就会不可用,于是在Hadoop 2.x给出了Hdfs的高可用方案,如下图所示:

  1. HA

    HDFS的高可用(High Availability,HA)方案就是为了解决Hadoop 1.x的单点故障问题而提出的。上图给出了一个基于HA的HDFS集群架构,在HA HDFS集群中会同时运行两个Namenode,一个作为活动的(Active)Namenode,一个作为备份的(Standby)Namenode。Active Namenode的命名空间与Standby Namenode是实时同步的,当Active Namenode发生故障时,Standby Namenode可以立即切换为活动状态,不会影响HDFS集群的读写服务。

  2. HA实现原理

    为了使Standby节点与Active节点的元数据状态能够同步一致,在运行过程中两个节点都需要会和一组独立运行的节点 (Journal Nodes,JNS)通信,当Active Namenode修改了修改命名空问时,它会将执行的操作记录在edit log中,并写入JNS的多数节点中,而Standby Namenode会一直监听JNS上edit log的变化,如果发现editlog有改动,Standby Namenode就会读取editlog并与当前的命名空间合并。

    当NameNode发生故障切换时,Standby节点会先保证已经从JNS上读取了所有的edit log并与自己的命名空间完成合并,然后才会从Standby状态切换为Active状态。通过这种机制,保证了Active Namenode与 Standby Namenode之间命名空间状态的一致性。而对于数据块与数据节点对应关系的一致性,则要求HDFS集群中的所有Datanode同时向这两个Namenode 发送心跳以及块汇报信息,这样Active Namenode和Standby Namenode的数据块与数据节点之间的对应关系也就完全同步了。 一旦发生故障,就可以马上切换,也就是热备

后面会重点介绍Hdfs 2.x的HA机制

总结

本次文章简单介绍了Hdfs的一些基础知识和架构,后面本系列会基于《Hadoo 2.x HDFS源码剖析》这本书来介绍HDFS

相关推荐
lzhlizihang1 天前
Hadoop的一些高频面试题 --- hdfs、mapreduce以及yarn的面试题
大数据·hadoop·hdfs·mapreduce·面试题·yarn
JavaShooter7 天前
argodb自定义函数读取hdfs文件的注意点,避免FileSystem已关闭异常
大数据·hadoop·hdfs
无休居士8 天前
分布式存储系统中HDFS和OSS有什么区别?如何选择?
大数据·hadoop·hdfs·oss对象云存储·oss迁移
Mephisto.java10 天前
【Hadoop|HDFS篇】NameNode和SecondaryNameNode
大数据·hadoop·hdfs
Mephisto.java13 天前
【Hadoop|HDFS篇】HDFS的读写流程
大数据·hadoop·hdfs
Mephisto.java13 天前
【Hadoop|HDFS篇】DataNode
大数据·hadoop·hdfs
Mephisto.java15 天前
【Hadoop|HDFS篇】HDFS的Shell操作
大数据·hadoop·hdfs
知其_所以然17 天前
Hadoop之HDFS的原理和常用命令及API(java)
大数据·hadoop·hdfs
呆呆不呆~23 天前
flink--会话模式与应用模式
大数据·hdfs·zookeeper·flink·kafka
呆呆不呆~1 个月前
数据采集-->kafka-->hdfs
大数据·分布式·hdfs·kafka·flume