Hadoop------HDFS

首先让我们来重温一下 hadoop 的四大组件:
HDFS:分布式存储系统
MapReduce:分布式计算系统
YARN: hadoop 的资源调度系统
Common: 以上三大组件的底层支撑组件,主要提供基础工具包和 RPC 框架等

 

概述:HDFS即Hadoop Distributed File System分布式文件系统,它的设计目标是把超大数据集存储到分布在网络中的多台普通商用计算机上,并且能够提供高可靠性和高吞吐量的服务。分布式文件系统要比普通磁盘文件系统复杂,因为它要引入网络编程,分布式文件系统要容忍节点故障也是一个很大的挑战。

 

设计前提和目标

  1. 专为存储超大文件而设计:hdfs应该能够支持GB级别大小的文件;它应该能够提供很大的数据带宽并且能够在集群中拓展到成百上千个节点;它的一个实例应该能够支持千万数量级别的文件。
  2. 适用于流式的数据访问:hdfs适用于批处理的情况而不是交互式处理;它的重点是保证高吞吐量而不是低延迟的用户响应
  3. 容错性:完善的冗余备份机制
  4. 支持简单的一致性模型:HDFS需要支持一次写入多次读取的模型,而且写入过程文件不会经常变化
  5. 移动计算优于移动数据:HDFS提供了使应用计算移动到离它最近数据位置的接口
  6. 兼容各种硬件和软件平台

不适合的场景

  1. 大量小文件文件的元数据都存储在NameNode内存中,大量小文件会占用大量内存。

  2. 低延迟数据访问:hdfs是专门针对高数据吞吐量而设计的
  3. 多用户写入,任意修改文件

hdfs架构设计

HDFS主要由3个组件构成,分别是NameNodeSecondaryNameNodeDataNode,HSFS是以master/slave模式运行的,其中NameNode、SecondaryNameNode 运行在master节点,DataNode运行slave节点

 

数据块是存储在DataNode中的,为了能够容错数据块是以多个副本的形式分布在集群中的,副本数量默认为3,

 

当一个客户端请求一个文件或者存储一个文件时,它需要先知道具体到哪个DataNode上存取,获得这些信息后,客户端再直接和这个DataNode进行交互,而这些信息的维护者就是NameNode。

NameNode管理着文件系统命名空间,它维护这文件系统树及树中的所有文件和目录。NameNode也负责维护所有这些文件或目录的打开、关闭、移动、重命名等操作。对于实际文件数据的保存与操作,都是由DataNode负责。当一个客户端请求数据时,它仅仅是从NameNode中获取文件的元信息,而具体的数据传输不需要经过NameNode,是由客户端直接与相应的DataNode进行交互。

 

NameNode保存元信息的种类有:

  • 文件名目录名及它们之间的层级关系
  • 文件目录的所有者及其权限
  • 每个文件块的名及文件有哪些块组成

NameNode元信息并不包含每个块的位置信息,这些信息会在NameNode启动时从各个DataNode获取并保存在内存中,因为这些信息会在系统启动时由数据节点重建。不过NameNode元信息会保存各个块的名称及文件由哪些块组成。

 

一般来说,一条元信息记录会占用200byte内存空间。假设块大小为64MB,备份数量是3 ,那么一个1GB大小的文件将占用16*3=48个文件块。如果现在有1000个1MB大小的文件,则会占用1000*3=3000个文件块(多个文件不能放到一个块中)。我们可以发现,如果文件越小,存储同等大小文件所需要的元信息就越多,所以,Hadoop更喜欢大文件。

 

为了简化系统的设计,Hadoop只有一个NameNode,这也就导致了hadoop集群的单点故障问题。因此,对NameNode节点的容错尤其重要,hadoop提供了如下两种机制来解决:

  • 将hadoop元数据写入到本地文件系统的同时再实时同步到一个远程挂载的网络文件系统(NFS)。
  • 运行一个secondary NameNode,它的作用是与NameNode进行交互,定期通过编辑日志文件合并命名空间镜像,当NameNode发生故障时它会通过自己合并的命名空间镜像副本来恢复。需要注意的是secondaryNameNode保存的状态总是滞后于NameNode,所以这种方式难免会导致丢失部分数据(后面会详细介绍)。

 

元信息的持久化

在NameNode中存放元信息的文件是 fsimage。在系统运行期间所有对元信息的操作都保存在内存中并被持久化到另一个文件edits中。并且edits文件和fsimage文件会被SecondaryNameNode周期性的合并

 

SecondaryNameNode的角色就是定期的合并edits和fsimage文件,我们来看一下合并的步骤:

  1. 合并之前告知NameNode把所有的操作写到新的edites文件并将其命名为edits.new。
  2. SecondaryNameNode从NameNode请求fsimage和edits文件
  3. SecondaryNameNode把fsimage和edits文件合并成新的fsimage文件
  4. NameNode从SecondaryNameNode获取合并好的新的fsimage并将旧的替换掉,并把edits用第一步创建的edits.new文件替换掉
  5. 更新fstime文件中的检查点

 

  • fsimage :保存的是上个检查点的HDFS的元信息
  • edits :保存的是从上个检查点开始发生的HDFS元信息状态改变信息
  • fstime:保存了最后一个检查点的时间戳

NameNode负责各个数据块的备份,DataNode会通过心跳的方式定期的向NameNode发送自己节点上的Block 报告,这个报告中包含了DataNode节点上的所有数据块的列表

 

而在Hadoop中,如果副本数量是3的情况下,Hadoop默认是这么存放的,把第一个副本放到机架的一个节点上,另一个副本放到同一个机架的另一个节点上,把最后一个节点放到不同的机架上。这种策略减少了跨机架副本的个数提高了写的性能,也能够允许一个机架失败的情况,算是一个很好的权衡。

 

关于副本的选择,在读的过程中,HDFS会选择最近的一个副本给请求者。

 

HDFS中的沟通协议

所有的HDFS中的沟通协议都是基于tcp/ip协议

一个客户端通过指定的tcp端口与NameNode机器建立连接,并通过ClientProtocol协议与NameNode交互。而DataNode则通过DataNode Protocol协议与NameNode进行沟通。

HDFS的RCP(远程过程调用)对ClientProtocol和DataNode Protocol做了封装。

按照HDFS的设计,NameNode不会主动发起任何请求,只会被动接受来自客户端或DataNode的请求。

 

可靠性保证

可以允许DataNode失败。DataNode会定期(默认3秒)的向NameNode发送心跳,若NameNode在指定时间间隔内没有收到心跳,它就认为此节点已经失败。此时,NameNode把失败节点的数据(从另外的副本节点获取)备份到另外一个健康的节点。这保证了集群始终维持指定的副本数。

 

hdfs文件读写过程剖析-----客户端与NameNode和DataNode的交互过程

hdfs文件读取过程:

hdfs有一个FileSystem实例,客户端通过调用这个实例的open()方法就可以打开系统中希望读取的文件。hdfs通过rpc调用NameNode获取文件块的位置信息,对于文件的每一个块,NameNode会返回含有该块副本的DataNode的节点地址,另外,客户端还会根据网络拓扑来确定它与每一个DataNode的位置信息,从离它最近的那个DataNode获取数据块的副本

hdfs会返回一个FSDataInputStream对象,FSDataInputStream类转而封装成DFSDataInputStream对象,这个对象管理着与DataNode和NameNode的I/O,具体过程是:

1. 客户端发起读请求
2. 客户端与NameNode得到文件的块及位置信息列表
3. 客户端直接和DataNode交互读取数据
4. 读取完成关闭连接

è¿éåå¾çæè¿°

这样设计的巧妙之处:

  1. 让客户端直接联系DataNode检索数据,可以使hdfs扩展到大量的并发客户端,因为数据流就是分散在集群的每个节点上的,在运行MapReduce任务时,每个客户端就是一个DataNode节点。
  2. NameNode仅需相应块的位置信息请求(位置信息在内存中,速度极快),否则随着客户端的增加,NameNode会很快成为瓶颈。

hdfs文件写入过程:

hdfs有一个DistributedFileSystem实例,客户端通过调用这个实例的create()方法就可以创建文件。DistributedFileSystem会发送给NameNode一个RPC调用,在文件系统的命名空间创建一个新文件,在创建文件前NameNode会做一些检查,如文件是否存在,客户端是否有创建权限等,若检查通过,NameNode会为创建文件写一条记录到本地磁盘的EditLog,若不通过会向客户端抛出IOException。

创建成功之后DistributedFileSystem会返回一个FSDataOutputStream对象,客户端由此开始写入数据。

同读文件过程一样,FSDataOutputStream类转而封装成DFSDataOutputStream对象,这个对象管理着与DataNode和NameNode的I/O,具体过程是:

1. 客户端在向NameNode请求之前先写入文件数据到本地文件系统的一个临时文件
2. 待临时文件达到块大小时开始向NameNode请求DataNode信息
3. NameNode在文件系统中创建文件并返回给客户端一个数据块及其对应DataNode的地址列表(列表中包含副本存放的地址)
4. 客户端通过上一步得到的信息把创建临时文件块flush到列表中的第一个DataNode
5. 当文件关闭,NameNode会提交这次文件创建,此时,文件在文件系统中可见

 è¿éåå¾çæè¿°

上面第四步描述的flush过程实际处理过程比较负杂,现在单独描述一下:

1. 首先,第一个DataNode是以数据包(数据包一般4KB)的形式从客户端接收数据的,DataNode在把数据包写入到本地磁盘的同时会向第二个DataNode(作为副本节点)传送数据。
2. 在第二个DataNode把接收到的数据包写入本地磁盘时会向第三个DataNode发送数据包
3. 第三个DataNode开始向本地磁盘写入数据包。此时,数据包以流水线的形式被写入和备份到所有DataNode节点
4. 传送管道中的每个DataNode节点在收到数据后都会向前面那个DataNode发送一个ACK,最终,第一个DataNode会向客户端发回一个ACK
5. 当客户端收到数据块的确认之后,数据块被认为已经持久化到所有节点。然后,客户端会向NameNode发送一个确认
6. 如果管道中的任何一个DataNode失败,管道会被关闭。数据将会继续写到剩余的DataNode中。同时NameNode会被告知待备份状态,NameNode会继续备份数据到新的可用的节点
7. 数据块都会通过计算校验和来检测数据的完整性,校验和以隐藏文件的形式被单独存放在hdfs中,供读取时进行完整性校验

 

hdfs文件删除过程

hdfs文件删除过程一般需要如下几步:

1. 一开始删除文件,NameNode只是重命名被删除的文件到/trash目录,因为重命名操作只是元信息的变动,所以整个过程非常快。在/trash中文件会被保留一定间隔的时间(可配置,默认是6小时),在这期间,文件可以很容易的恢复,恢复只需要将文件从/trash移出即可。
2. 当指定的时间到达,NameNode将会把文件从命名空间中删除
3. 标记删除的文件块释放空间,HDFS文件系统显示空间增加

关于hadoop与网络拓扑

在海量数据处理过程中,主要限制因素是节点之间的带宽。衡量两个节点之间的带宽往往很难实现,在这里hadoop采取了一个简单的方法,它把网络拓扑看成是一棵树,连个节点的距离=它们到最近共同祖先距离的总和,而树的层次可以这么划分:

  • 同一节点中的进程
  • 同一机架上的不同节点
  • 同一数据中心不同机架
  • 不同数据中心的节点

若数据中心d1中一个机架r1中一个节点n1表示为d1/r1/n1,则:

 distance(d1/r1/n1,d1/r1/n1)=0;
 distance(d1/r1/n1,d1/r1/n2)=2;
 distance(d1/r1/n1,d1/r2/n3)=4;
 distance(d1/r1/n1,d2/r3/n4)=6;

 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值