您的位置:首页 > 大数据 > Hadoop

HDFS 概述(二)

2020-06-06 05:34 267 查看

HDFS体系架构与数据读写

1、HDFS 整体架构

HDFS 是一个主从 Master/Slave 架构。
一个 HDFS 集群包含一个 NameNode,这是一个 Master Server,用来管理文件系统的命名空间,以及调节客户端对文件的访问。
一个 HDFS 集群还包括多个 DataNode,用来存储数据。
HDFS 的整体结构如下图所示:

HDFS 会对外暴露一个文件系统命名空间,并允许用户数据以文件的形式进行存储。在内部,一个文件被分成多个块并且这些块被存储在一组 DataNode 上。
1)NameNode

文件的元数据采用集中式存储方案存放在 NameNode 当中。NameNode 负责执行文件系统命名空间的操作,如打幵、关闭、重命名文件和目录。NameNode 同时也负责将数据块映射到对应的 DataNode 中。

2)DataNode

DataNode 是文件系统的工作结点。它们根据需要存储并检索数据块,并且定期向 NameNode发送他们所存储的块的列表。文件数据块本身存储在不同的 DataNode 当中,DataNode 可以分布在不同机架上。
DataNode负责服务文件系统客户端发出的读/写请求。
DataNode 同时也负责接收 NameNode 的指令来进行数据块的创建、删除和复制。

3)Client

HDFS 的 Client 会分别访问 NameNode 和 DataNode 以获取文件的元信息及内容。HDFS 集群的 Client将直接访问 NameNode 和 DataNode,相关数据会直接从 NameNode 或者 DataNode 传送到客户端。

NameNode 和 DataNode 都是被设计为在普通 PC 上运行的软件程序。HDFS 是用 Java 语言实现的,任何支持 Java 语言的机器都可以运行 NameNode 或者 DataNode。
Java 语言本身的可移植性意味着 HDFS 可以被广泛地部署在不同的机器上。
一个典型的部署就是,集群中的一台专用机器运行 NameNode,集群中的其他机器每台运行一个 DataNode 实例。
该架构并不排除在同一台机器上运行多个 DataNode 实例的可能,但在实际的部署中很少会这么做。
单一 NameNode 的设计极大地简化了集群的系统架构,它使得所有 HDFS 元数据的仲裁和存储都由单一 NameNode 来决定,避免了数据不一致性的问题。

2、HDFS 数据复制

HDFS 可以跨机架、跨机器,可靠地存储海量文件。HDFS 把每个文件存储为一系列的数据块,除了最后一个数据块以外,一个文件的所有数据块都是相同大小的。(1秒定律,128M)
每个数据块都有一个副本。
为了容错,一个文件的数据块会被复制。对于每个文件来说,文件块大小和复制因子都是可配置的。应用程序可以声明一个文件的副本数。复制因子可以在文件创建时声明,并且可以在以后修改。
NameNode 控制所有的数据块的复制决策。
它周期性地从集群中的 DataNode 中收集心跳和数据块报告。
收集到心跳则意味着 DataNode 正在提供服务。
收集到的数据块报告会包含相应 DataNode 上的所有数据块列表。

复制因子:规定每个数据块的副本个数
通用场景下,当复制因子(Replication)是 3时,HDFS 的复制策略是将一个副本放置到本地机架的一个结点上,另一个放在本地机架的不同结点上,最后一个放在不同机架的不同结点上。
HDFS 复制策略与把 3个副本放在 3个不同机架上的策略相比,减少了机架之间的写操作,从而提升了写性能。

当一切运行正常时,DataNode 会周期性发送心跳信息给 NameNode(默认是每 3 秒钟一次)。
如果 NameNode 在预定的时间内没有收到心跳信息(默认是 10 分钟),就会认为 DataNode 出现了问题,这时候就会把该 DataNode 从集群中移除,并且启动一个进程去恢复数据。
DataNode 脱离集群的原因有多种,如硬件故障、主板故障、电源老化和网络故障等。
对于 HDFS 来说,丢失一个 DataNode 意味着丢失了存储在它的硬盘上的数据块的副本。
假如在任意时间总有超过一个副本存在,故障将不会导致数据丢失。(如果副本丢失,namenode会通知其他机器进行备份)
当一个硬盘故障时,HDFS 会检测到存储在该硬盘上的数据块的副本数量低于要求,然后主动创建需要的副本,以达到满副本数状态。

3、HDFS读取和写入数据

HDFS 的文件访问机制为流式访问机制,即通过 API 打开文件的某个数据块之后,可以顺序读取或者写入某个文件。
由于 HDFS 中存在多个角色,且对应的应用场景主要为一次写入、多次读取的场景,因此其读和写的方式有较大不同。读/写操作都由客户端发起,并且由客户端进行整个流程的控制,NameNode 和 DataNode 都是被动式响应。

1)读取流程

客户端发起读取请求时,首先与 NameNode 进行连接。
连接建立完成后,客户端会请求读取某个文件的某一个数据块。NameNode在内存中进行检索,查看是否有对应的文件及文件块,若没有则通知客户端对应文件或数据块不存在,若有则通知客户端对应的数据块存在哪些服务器之上。
客户端接收到信息之后,与对应的 DataNode 连接,并开始进行数据传输。客户端会选择离它最近的一个副本数据进行读操作。

读取文件的具体过程如下图所示:

  1. 客户端调用 DistributedFileSystem 的 Open() 方法打开文件。
  2. DistributedFileSystem 用 RPC 连接到 NameNode,请求获取文件的数据块的信息;NameNode 返回文件的部分或者全部数据块列表;对于每个数据块,NameNode 都会返回该数据块副本的 DataNode 地址;DistributedFileSystem 返回 FSDataInputStream 给客户端,用来读取数据。
  3. 客户端调用 FSDataInputStream 的 Read() 方法开始读取数据。
  4. FSInputStream 连接保存此文件第一个数据块的最近的 DataNode,并以数据流的形式读取数据;客户端多次调用 Read(),直到到达数据块结束位置。
  5. FSInputStream连接保存此文件下一个数据块的最近的 DataNode,并读取数据。
  6. 当客户端读取完所有数据块的数据后,调用 FSDataInputStream 的 Close() 方法。

在读取数据的过程中,如果客户端在与数据结点通信时出现错误,则尝试连接包含此数据块的下一个数据结点。失败的数据结点将被记录,并且以后不再连接。

2)写入流程

写入文件的过程比读取较为复杂,在不发生任何异常情况下,客户端向 HDFS 写入数据的流程如图 2 所示,具体步骤如下。

  1. 客户端调用 DistribuedFileSystem 的 Create() 方法来创建文件。
  2. DistributedFileSystem 用 RPC 连接 NameNode,请求在文件系统的命名空间中创建一个新的文件;NameNode 首先确定文件原来不存在,并且客户端有创建文件的权限,然后创建新文件;DistributedFileSystem 返回 FSOutputStream 给客户端用于写数据。
  3. 客户端调用 FSOutputStream 的 Write() 函数,向对应的文件写入数据。
  4. 当客户端开始写入文件时,FSOutputStream 会将文件切分成多个分包(Packet),并写入其內部的数据队列。FSOutputStream 向 NameNode 申请用来保存文件和副本数据块的若干个 DataNode,这些 DataNode 形成一个数据流管道。
    队列中的分包被打包成数据包,发往数据流管道中的第一个 DataNode。第一个 DataNode 将数据包发送给第二个 DataNode,第二个 DataNode 将数据包发送到第三个 DataNode。这样,数据包会流经管道上的各个 DataNode。
  5. 为了保证所有 DataNode 的数据都是准确的,接收到数据的 DataNode 要向发送者发送确认包(ACK Packet)。确认包沿着数据流管道反向而上,从数据流管道依次经过各个 DataNode,并最终发往客户端。当客户端收到应答时,它将对应的分包从内部队列中移除。相当于写完的响应、回馈
  6. 不断执行第 (3)~(5)步,直到数据全部写完。
  7. 调用 FSOutputStream 的 Close() 方法,将所有的数据块写入数据流管道中的数据结点,并等待确认返回成功。最后通过 NameNode 完成写入。

问题 : 客户端是怎么将数据传输给DataNode的呢? 是通过NIO
向HDFS上传文件时,主要是通过DistributedFileSystem里的DFSOutputStream实现。
DFSOutputStream 中有个 DataStreamerstreamer(负责开启线程,通过nio的方式将Packet传输至hdfs) 对象
DataStreamer 里有个 DataOutputStream blockStream (里面实现了SocketOutputStream接口,负责发送Packet)
文件数据的传输单位为Packet,一个Packet默认大小为64K,一个Packet中含有多个chunk,chunk为校验数据的单位,默认大小512byte。

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: