TypechoJoeTheme

顿搜

统计

03. HDFS分布式文件系统——大数据专栏

2022-07-20
/
0 评论
/
102 阅读
/
正在检测是否收录...
07/20

HDFS的概念

HDFS是Hadoop项目的核心子项目,是分布式计算中数据存储管理的基础,是基于流式数据访问和处理超大文件的需求而开发的分布式文件系统。

整个系统可以运行在由廉价的商用服务器组成的集群之上,它所具有的高容错性、高可靠性、高可扩展性、高可用性、高吞吐率等特征,为海量数据提供了不怕故障的存储,给超大数据集的应用处理带来了很多便利

HDFS产生的背景

数据量的不断增大导致数据在一个操作系统管辖的范围内存储不下,为了存储这些大规模数据,需要将数据分配到更多操作系统管理的磁盘中存储,但是这样处理会导致数据的管理和维护很不方便,所以迫切需要一种系统来管理和维护多台机器上的数据文件,这种系统就是分布式文件管理系统,而HDFS只是分布式文件管理系统中的一种

HDFS的设计理念

HDFS的设计理念来源于非常朴素的思想:即当数据文件的大小超过单台计算机的存储能力时,就有必要将数据文件切分并存储到由若干台计算机组成的集群中,这些计算机通过网络进行连接,而HDFS作为一个抽象层架构在集群网络之上,对外提供统一的文件管理功能,对于用户来说感觉像在操作一台计算机一样,根本感受不到HDFS底层的多台计算机,而且HDFS还能够很好地容忍节点故障且不丢失任何数据。

HDFS的核心设计目标

  • 支持超大文件存储
  • 流式数据访问

流式数据访问是HDFS选择的最高效的数据访问方式。

HDFS选择采用一次写入、多次读取的流式数据访问模式,而不是随机访问模式。

  • 简单的一致性模型

在HDFS中,一个文件一旦创建、写入、关闭,一般不需要再进行修改。这样就可以简单地保证数据的一致性。

  • 硬件故障的检测和快速应对

HDFS的系统架构

HDFS系统架构是一个主从架构。一个典型的HDFS集群中,通常会有一个NameNode,一个SecondaryNameNode和至少一个DataNode,而且HDFS客户端的数量也没有限制。

NameNode

NameNode是HDFS主从架构中的主节点,也被称为名字节点、管理节点或元数据节点,它管理文件系统的命名空间,维护着整个文件系统的目录树以及目录树中的所有子目录和文件。

这些信息还以两个文件的形式持久化保存在本地磁盘上,一个是命名空间镜像,也称为文件系统镜像FSImage(File System Image, FSImage),主要用来存储HDFS的元数据信息,是HDFS元数据的完整快照。每次NameNode启动时,默认都会加载最新的命名空间镜像文件到内存中。

还有一个文件是命名空间镜像的编辑日志(Edit Log),该文件保存用户对命名空间镜像的修改信息。

SecondaryNameNode

SecondaryNameNode是HDFS主从架构中的备用节点,也被称为从元数据节点,主要用于定期合并FSImage和命名空间镜像的Edit Log,是一个辅助NameNode的守护进程。

在生产环境下,SecondaryNameNode一般会单独地部署到一台服务器上,因为SecondaryNameNode节点在进行两个文件合并时需要消耗大量资源。

FSImage文件实际上是HDFS文件系统元数据的一个永久性检查点(CheckPoint)

交互过程

(1) SecondaryNameNode(即从元数据节点)引导NameNode(即元数据节点)滚动更新编辑日志,并将新的编辑日志写进edits.new。

(2) SecondaryNameNode将NameNode的FSImage文件(fsimage)和编辑日志Edit Log(edits)文件复制到本地的检查点目录。

(3) SecondaryNameNode将FSImage(fsimage)文件导入内存,回放编辑日志(edits),将其合并到FSImage(fsimage.ckpt),并将新的FSImage文件(fsimage.ckpt)压缩后写入磁盘。

(4) SecondaryNameNode将新的FSImage文件(fsimage.ckpt)传回NameNode。

(5) NameNode在接收到新的FSImage文件(fsimage.ckpt)后,将fsimage.ckpt替换为fsimage,然后直接加载和启用该文件。

(6) NameNode将Edit Log.new(即图中的edits.new)更名为Edit Log(即图中的edits)。

默认情况下,该过程1h发生一次,或当编辑日志达到默认值(如64MB)触发。具体触发该操作的值是可以通过配置文件配置的。

DataNode

  • DataNode节点是以数据块的形式在本地Linux文件系统上保存HDFS文件的内容,并对外提供文件数据访问功能。
  • DataNode节点的一个基本功能就是管理这些保存在Linux文件系统中的数据
  • DataNode节点是将数据块以Linux文件的形式保存在本节点的存储系统上

HDFS客户端

HDFS客户端便于用户和HDFS进行交互,HDFS提供了非常多的客户端,包括命令行接口、Java API、Thrift接口、Web界面。

数据块

磁盘有数据块(也叫磁盘块)的概念,每个磁盘都有默认的磁盘块容量,磁盘块容量一般为512字节,这是磁盘进行数据读写的最小单位

文件系统也有数据块的概念,但是文件系统中的块的容量只能是磁盘块容量的整数倍,一般为几千字节

HDFS也有数据块(Block)的概念,但是HDFS的数据块比一般文件系统的数据块要大得多,它也是HDFS存储处理数据的最小单元。默认为64MB或128MB

不同版本的Hadoop默认的块的大小不一样,Hadoop 2.x版本以后默认数据块的大小为128MB,而且可以根据实际的需求,通过配置hdfs-site.xml文件中的dfs.block.size属性来改变块的大小。
HDFS中小于一个块大小的文件并不会占据整个块的空间。

为什么数据块这么大

HDFS的数据块大是为了最小化寻址开销。

因为如果块设置得足够大,从磁盘传输数据的时间可以明显大于定位到这个块开始位置所需要的时间。

所以要将块设置得尽可能大一点,但是也不能太大,因为这些数据块最终是要供上层的计算框架处理的,如果数据块太大,那么处理整个数据块所花的时间就比较长,会影响整体数据处理的时间

HDFS的优缺点

HDFS的优点

  • 高容错性

数据自动保存多个副本,HDFS通过增加多个副本的形式,提高了HDFS文件系统的容错性;某一个副本丢失以后可以自动恢复。

  • 适合大数据处理。

能够处理GB、TB、甚至PB级别的数据规模;能够处理百万规模以上的文件数量;能够处理10000个以上节点的集群规模。

  • 流式文件访问。

数据文件只能一次写入,多次读取,只能追加,不能修改;HDFS能保证数据的简单一致性。

  • 可构建在廉价的机器上。

HDFS通过多副本机制,提高了整体系统的可靠性;HDFS提供了容错和恢复机制。

比如某一个副本丢失,可以通过其他副本来恢复。保证了数据的安全性和系统的可靠性。

HDFS的缺点

  • 不适合低延时数据访问

比如ms级别的数据响应时间,这种场景HDFS是很难做到的。HDFS更适合高吞吐率的场景,即在某一时间内写入大量的数据。

  • 不适合大量小文件的存储

如果有大量小文件需要存储,这些小文件的元数据信息的存储会占用NameNode大量的内存空间。这样是不可取的,因为NameNode的内存总是有限的;

如果小文件存储的寻道时间超过文件数据的读取时间,这样也是不行的,它违反了HDFS大数据块的设计目标。

  • 不适合并发写入、文件随机修改。

一个文件只能有一个写操作,不允许多个线程同时进行写操作;仅支持数据的append(追加)操作,不支持文件的随机修改。

HDFS的读数据流程

(1)首先调用FileSystem对象的open()方法,其实获取的是一个分布式文件系统(DistributedFile-System)实例)

(2)分布式文件系统(DistributedFileSystem)通过远程过程调用(Remote Procedure Call, RPC)获得文件第一批块(Block)的位置信息(Locations),同一个块按照重复数会返回多个位置信息,这些位置信息按照Hadoop拓扑结构排序,距客户端近的排在前面。

(3)前两步会返回一个文件系统数据输入流(FSDataInputStream)对象,该对象会被封装为分布式文件系统输入流(DFSInputStream)对象,DFSInputStream可以方便地管理DataNode和NameNode数据流。客户端调用read()方法,DFSInputStream会找出离客户端最近的DataNode并连接。

(4)数据从DataNode源源不断地流向客户端。

(5)如果第一个块的数据读取完毕,就会关闭指向第一个块的DataNode的连接,接着读取下一个块。这些操作对客户端来说是透明的,从客户端的角度看来只是在读一个持续不断的数据流。

(6)如果第一批块都读取完毕,DFSInputStream就会去NameNode获取下一批块的位置信息,然后继续读取,如果所有的块都读取完毕,这时就会关闭掉所有的流。

  • 如果在读数据时,DFSInputStream和DataNode的通信发生异常,就会尝试连接正在读取的块的排序第二近的DataNode,并且会记录哪个DataNode发生错误,剩余的块读取时就会直接跳过该DataNode。
  • DFSInputStream也会检查块数据校验和,如果发现一个坏的块,就会先报告到NameNode,然后DFSInputStream在其他的DataNode上读取该块的数据。
  • HDFS读数据流程的设计就是客户端直接连接DataNode来检索数据,并且NameNode来负责为每一个块提供最优的DataNode, NameNode仅仅处理块的位置请求,这些信息都加载在NameNode的内存中,HDFS通过DataNode集群可以承受大量客户端的并发访问。

HDFS的写数据流程

(1)客户端通过调用分布式文件系统(DistributedFileSystem)的create()方法创建新文件。

(2)DistributedFileSystem通过RPC调用NameNode去创建一个没有块关联的新文件,创建前,NameNode会做各种校验,比如文件是否存在,客户端有无权限去创建等。如果校验通过,NameNode会记录下新文件,否则会抛出I/O异常。

(3)前两步结束后,会返回文件系统数据输出流(FSDataOutputStream)的对象,与读文件时相似,FSDataOutputStream被封装成分布式文件系统数据输出流(DFSOutputStream)。DFSOutputStream可以协调NameNode和DataNode。客户端开始写数据到DFSOutputStream, DFSOutputStream会把数据切成一个个小的数据包(packet),然后排成数据队列(data quene)。

(4)数据队列中的数据包首先输出到数据管道(多个数据节点组成数据管道)中的第一个DataNode中(写数据包),第一个DataNode又把数据包发送到第二个DataNode中,依次类推。

(5)DFSOutputStream还维护着一个队列叫响应队列(ack quene),这个队列也是由数据包组成,用于等待DataNode收到数据后返回响应数据包,当数据管道中的所有DataNode都表示已经收到响应信息时,akc quene才会把对应的数据包移除掉。

(6)客户端完成写数据后,调用close()方法关闭写入流

(7)客户端通知NameNode把文件标记为已完成。然后NameNode把文件写成功的结果反馈给客户端。此时就表示客户端已完成了整个HDFS的写数据流程。

如果在写的过程中某个DataNode发生错误,会采取以下步骤处理。

(1)管道关闭。

(2)正常的DataNode上正在写的块会有一个新ID(需要和NameNode通信),失败的DataNode上不完整的块在上报心跳时会被删掉。

(3)失败的DataNode会被移出数据管道,块中剩余的数据包继续写入管道中的其他两个DataNode。

(4)NameNode会标记这个块的副本个数少于指定值,块的副本会稍后在另一个DataNode创建。

(5)有时多个DataNode会失败,只要dfs.replication.min(缺省是1个)属性定义的指定个数的DataNode写入数据成功了,整个写入过程就算成功,缺少的副本会进行异步的恢复。

客户端执行write操作后,写完的块才是可见的,正在写的块对客户端是不可见的,只有调用sync()方法,客户端才确保该文件的写操作已经全部完成,当客户端调用close()方法时,会默认调用sync()方法。

HDFS的副本存放策略

副本技术优点

  • 提高系统可靠性

系统不可避免地会产生故障和错误,拥有多个副本的文件系统不会导致无法访问的情况,提高了系统的可用性。

另外,系统可以通过其他完好的副本对发生错误的副本进行修复,提高了系统的容错性。

  • 负载均衡

副本可以对系统的负载进行扩展。多个副本存放在不同的服务器上,可有效地分担工作量,从而将较大的工作量有效地分布在不同节点上。

  • 提高访问效率

将副本创建在访问频度较大的区域,即副本在访问节点的附近,相应减小了其通信开销,提高了整体的访问效率。

HDFS副本存放策略

HDFS的副本策略实际上就是NameNode如何选择在哪个DataNode存储副本(Replication)的问题

HDFS采用机架感知(Rack Awareness)的副本存放策略来提高数据的可靠性、可用性和网络带宽的利用率。

副本1存放在Client所在的节点上(假设Client不在集群的范围内,则第一个副本存储节点是随机选取的。当然系统会尝试不选择那些太满或太忙的节点)。

副本2存放在与第一个节点不同机架中的一个节点中(随机选择)

副本3和副本2在同一个机架,随机放在不同的节点中。

假设还有很多其他的副本随机放在集群中的各个节点上。具体副本数据复制流程如下。

1)当Client向HDFS文件写入数据时,一开始是写入本地临时文件中。

2)假设文件的副本个数设置为3,那么当Client本地临时文件累积到一个数据块的大小时,Client会从NameNode获取一个DataNode列表用于存放副本。然后Client开始向第一个DataNode中传输副本数据,第一个DataNode一小部分一小部分(4KB)地接收数据,将每一部分写入本地存储,并同一时间传输该部分到列表中第二个DataNode节点。第二个DataNode也是这样,一小部分一小部分地接收数据,写入本地存储,并同一时间传给第三个DataNode节点。最后,第三个DataNode接收数据并存储在本地。因此,DataNode能流水线式地从前一个节点接收数据,并同一时间转发给下一个节点,数据以流水线的方式从前一个DataNode复制到下一个DataNode。

HDFS的高可用(HA)

高可用(High Availability, HA),为了整个系统的可靠性,通常会在系统中部署两台或多台主节点,多台主节点形成主备的关系,但是某一时刻只有一个主节点能够对外提供服务,当某一时刻检测到对外提供服务的主节点“挂”掉之后,备用主节点能够立刻接替已挂掉的主节点对外提供服务,而用户感觉不到明显的系统中断。这样对用户来说整个系统就更加的可靠和高效。

影响HDFS集群不可用主要包括以下两种情况。

NameNode机器宕机,将导致集群不可用,重启NameNode之后才可使用。

NameNode机器宕机,将导致集群不可用,重启NameNode之后才可使用。

HA机制的产生背景

在Hadoop1.0的时代,HDFS集群中NameNode存在单点故障(SPOF)时,由于NameNode保存了整个HDFS的元数据信息,对于只有一个NameNode的集群,如果NameNode所在的机器出现意外情况,将导致整个HDFS系统无法使用。同时Hadoop生态系统中依赖于HDFS的各个组件,包括MapReduce、Hive、Pig以及HBase等也都无法正常工作,直到NameNode重新启动。重新启动NameNode和其进行数据恢复的过程也会比较耗时。这些问题在给Hadoop的使用者带来困扰的同时,也极大地限制了Hadoop的使用场景,使得Hadoop在很长的时间内仅能用作离线存储和离线计算,无法应用到对可用性和数据一致性要求很高的在线应用场景中。

HDFS的HA机制

DFS的HA通常由两个NameNode组成,一个处于Active状态,另一个处于Standby状态。

Active状态的NameNode对外提供服务,比如处理来自客户端的RPC请求;

而Standby状态的NameNode则不对外提供服务,仅同步Active状态的NameNode的状态,以便能够在它失败时快速进行切换。

HDFS的HA架构

  • 活跃的名字节点(Active NameNode)和备用的名字节点(Standby NameNode)

两个名字节点形成互备,一个处于Active状态,为主NameNode,另外一个处于Standby状态,为备用NameNode,只有主NameNode才能对外提供读写服务。

  • 主备切换控制器(ZKFailoverController)

主备切换控制器作为独立的进程运行,对NameNode的主备切换进行总体控制。主备切换控制器能及时检测到NameNode的健康状况,在主NameNode故障时借助Zookeeper实现自动的主备选举和切换,当然NameNode目前也支持不依赖于Zookeeper的手动主备切换

  • Zookeeper集群

为主备切换控制器提供主备选举支持。

  • 共享存储系统

共享存储系统即为存储数据的JournalNode集群(JournalNode为存储管理Editlog的守护进程)。

共享存储系统是实现NameNode高可用最为关键的部分,共享存储系统保存了NameNode在运行过程中所产生的HDFS的元数据。

主NameNode和备NameNode通过共享存储系统实现元数据同步。在进行主备切换时,新的主NameNode在确认元数据完全同步之后才能继续对外提供服务。

  • 数据节点(DataNode)

除了通过共享存储系统共享HDFS的元数据信息之外,主NameNode和备NameNode还需要共享HDFS的数据块和DataNode之间的映射关系。DataNode会同时向主NameNode和备NameNode上报数据块的位置信息。

HDFS联邦机制

虽然HDFS HA解决了单点故障的问题,但是在系统扩展性、整体性能和隔离性方面仍然存在问题。

  • 系统扩展性

元数据存储在NameNode内存中,受内存上限的制约。

  • 整体性能

吞吐量受单个NameNode的影响。

  • 隔离性:一个程序可能会影响其他运行的程序,如一个程序消耗过多资源导致其他程序无法顺利运行,HDFS HA本质上还是单名称节点。

HDFS引入联邦机制可以解决以上三个问题。

在HDFS联邦中,设计了多个相互独立的NameNode(名称节点),使得HDFS的命名服务能够水平扩展,这些NameNode分别进行各自命名空间和块的管理,不需要彼此协调

每个DataNode(数据节点)要向集群中所有的NameNode注册,并周期性地发送心跳信息和块信息,报告自己的状态

HDFS联邦拥有多个独立的命名空间,其中,每一个命名空间管理属于自己的一组块,属于同一个命名空间的块组成一个块池。每个DataNode会为多个块池提供块的存储,块池中的各个块实际上是存储在不同DataNode中。

朗读
赞 · 0
版权属于:

顿搜

本文链接:

https://dun.so/archives/2877/(转载时请注明本文出处及文章链接)