HDFS的运行原理,如何实现HDFS的高可用

时间:2021-06-17 01:26:39

1 HDFS的运行机制

HDFS集群中的节点分为两种角色,一种角色负责管理整个集群的元数据,是名称节点(name node);另一种角色负责存储文件数据块和管理文件数据块,是数据节点(datanode)。

1.1 NameNode

      1.1.1名称节点负责响应客户端的请求,负责管理整个文件系统的元数据。

       1.1.2HDFS的内部工作机制对客户端是透明的,客户端对HDFS的读、写操作都必须先向name node申请。所以元数据是关键。

       1.1.3负责维持文件的副本数量

       1.1.4 为了保证集群的元数据不丢失,生产环境下需要配置辅助名称节点(secondary name node,简称2NN)作为元数据的备份,万一name node的元数据丢失就可以从2NN恢复元数据。

       1.1.5 名称节点可用的前提是此节点运行名为“NameNode”的进程。

 HDFS的运行原理,如何实现HDFS的高可用

1.2 数据节点Data Node

1.2.1 负责存放被切割后的文件块。文件在data node的存储单位是块(block)。

1.2.2 如果hadoop集群是完全分布式模式,那么一个文件的每一个块必须有多个副本,存放在不同的datanode上。当客户端把某个文件写入HDFS时,首先按照固定的块大小(block size)把该文件切成若干个块,再分布式地存储在若干台data node上。

1.2.3 data node通过心跳信息定期地向name node汇报自身保存的文件块信息。

1.2.4 数据节点可用的前提是此节点运行名为“DataNode”的进程。

 

下面介绍一下客户端向HDFS写数据和读数据的流程,hadoop集群规模以“1台namenode + 3台data node”为例。

1.3 客户端向HDFS写数据的流程

1.3.1 客户端和name node通信,name node检查目标文件是否已存在,父目录是否存在,检查通过以后name node通知客户端可以写入

1.3.2 客户端向name node请求上传文件的第一个块(block1),询问name node应该把block1上传到哪些data node主机上。客户端每传一个block都要向name node请求

1.3.3 name node把3台data node服务器信息返回给客户端。基于可靠性的考虑,每个文件块都有副本,每个副本分别存放在不同的data node服务器上。副本存放的data node选择策略:首选在本地机架的一个节点上存放副本, 第二个副本在本地机架的另一个不同节点,第三个副本在不同机架的不同节点上

1.3.4 正式上传之前,客户端请求与3台中的其中一台(dn1)建立传输通道,dn1又和dn2主机建立传输通道,dn2又和dn3建立传输通道

1.3.5整个传输通道建立完成后,客户端把block1从磁盘读出来放到本地缓存, 开始向dn1上传block1,上传时以package为单位进行传输,package默认大小64kb。dn1每收到一个package就会复制一份传给dn2,dn2再复制一份传给dn3。

1.3.6 当block1传输完成后,客户端再次向name node申请上传此文件的第二个块block2

 

1.4 客户端从HDFS读数据的流程

1.4.1 客户端和name node通信,查询元数据,找到文件块存放的data node服务器信息

1.4.2 客户端收到name node返回的信息(例如block1存放在dn1和dn2上,block2在dn2和dn3上),去找到相应的dn(按就近挑选dn原则,然后随机),再请求和dn建立socket流

1.4.3 socket流建立好以后,dn开始向客户端发送数据(从磁盘读取数据放入socket流)

1.4.4 客户端以packet为单位接收文件块,把各个块在本地合并成一个完整的文件

 

1.5 名称节点是如何管理元数据的?

Name node对数据的管理采用了三种存储形式:memory meta data, fsimage, edit log.

1.5.1 memorymeta data:内存元数据。在name node服务器启动时会把fsimage从磁盘加载到内存,有了元数据就可以向客户端提供读、写服务了

1.5.2 fsimage是在磁盘中的元数据镜像文件,整个文件系统的元数据(包括所有目录和文件inode序列化信息)都永久保存在此文件里;它位于name node的工作目录中

1.5.3 edit logs是数据操作日志文件(可通过日志运算出元数据),客户端对HDFS中的文件进行写操作(增加或删除)之前,先把此操作行为记录到edit log文件中,再把成功操作代码发送给客户端。edit log需要定期通过checkpoint机制融合到fsimage,以保证name node的元数据是最新的,详见下面的描述。

 

1.6 若名称节点发生磁盘故障,如何挽救集群以及数据?

这个需要提前单独准备一台主机,专门用于部署辅助名称节点(2NN)。同时,name node(NN)和2NN的工作目录存储结构完全相同,这样一来,一旦NN服务器挂掉,可以从2NN的工作目录中将fsimage拷贝到NN的工作目录,以恢复元数据。注意:这种补救措施是事后的,不能保证内存中的元数据是最新的,因为2NN不能充当name node使用(只有name node才能及时更新元数据)。要想让HDFS集群持续对外提供服务,需要引入高可用(HA)配置,HDFS高可用的原理可继续阅读下文。

实际上2NN是用来备份NN中的元数据,备份的内容包括NN服务器上最新的fsimage文件以及全部的日志文件(edit log),备份的过程叫做checkpoint(检查点),过程概要:每隔一段时间,会由2NN将NN上积累的所有edits和一个最新的fsimage下载到2NN本地,并加载到内存进行merge(融合),再把融合后的文件上传给NN。具体checkpoint流程如下:

1.6.1 在做检查点之前,先让NN上正在写的日志文件滚动一下,以供2NN拷贝。日志文件和fsimage的路径可从配置文件hdfs-site.xml的dfs.namenode.name.dir属性中找到,例如我的元数据存放的路径是/home/centos/namemeta

       <property>

              <name>dfs.namenode.name.dir</name>

              <value>/home/centos/namemeta</value>

       </property>

下面有个子目录current存放所有的fsimage和edit log文件,查看此目录的树结构:

current/
|-- edits_0000000000000010612-0000000000000010613
|-- edits_0000000000000010614-0000000000000010615
|-- edits_0000000000000010616-0000000000000010617
|-- edits_inprogress_0000000000000010618
|-- fsimage_0000000000000010472
|-- fsimage_0000000000000010472.md5
|-- fsimage_0000000000000010563
|-- fsimage_0000000000000010563.md5
`-- seen_txid

1.6.2 在HDFS集群首次做检查点时才会从NN下载最新的fsimage文件,以后做检查点时只需下载NN上的edit log(因为editlog比fsimage要小)。2NN有了fsimage和editlog,就可以在2NN服务器的内存中对二者进行融合,生成一个检查点文件fsimage.checkpoint,再把此文件上传到NN并重命名为fsimage文件

1.6.3 NN根据刚才2NN传来的最新fsimage更新内存中的元数据

1.6.4 默认是间隔30分钟做一次checkpoint

 

 

2 如何实现HDFS高可用

HDFS的高可用指的是HDFS持续对各类客户端提供读、写服务的能力,因为客户端对HDFS的读、写操作之前都要访问name node服务器,客户端只有从name node获取元数据之后才能继续进行读、写。所以HDFS的高可用的关键在于name node上的元数据持续可用。

前面说过2NN的功能是checkpoint,把NN的fsimage和edit log做定期融合,融合后传给NN, 以确保备份到的元数据是最新的,这一点类似于做了一个元数据的快照。Hadoop官方提供了一种quorum journal manager来实现高可用,那么就没必要配置2NN了。

在高可用配置下,edit log不再存放在名称节点,而是存放在一个共享存储的地方,这个共享存储由若干个Journal Node组成,一般是3个节点(JN小集群), 每个JN专门用于存放来自NN的编辑日志,编辑日志由活跃状态的名称节点写入。

要有2个名称节点,二者之中只能有一个处于活跃状态(active),另一个是待命状态(standby),只有active节点才能对外提供读写HDFS服务,也只有active态的NN才能向JN写入编辑日志;standby的名称节点只负责从JN小集群中的JN节点拷贝数据到本地存放。另外,各个DATA NODE也要同时向两个名称节点报告状态(心跳信息、块信息)。

       那么一主一从的2个名称节点同时和3个JN构成的组保持通信,活跃的名称节点负责往JN集群写入编辑日志,待命的名称节点负责观察JN组中的编辑日志,并且把日志拉取到待命节点。再加上俩节点各自的fsimage镜像文件,这样一来就能确保两个NN的元数据保持同步。一旦active不可用,提前配置的zookeeper会把standby节点自动变为active,继续对外提供服务。详见下文的 2.2如何通过自动容灾而不是手动容灾?

 

2.1手动实现高可用的大概流程:

2.1.1 准备3台服务器分别用于运行JournalNode进程(也可以运行在date node服务器上),准备2台namenode服务器用于运行NameNode进程,数据节点数量不限

2.1.2 分别启动3台JN服务器上的JournalNode进程,分别在date node服务器启动DataNode进程

2.1.3 需要同步2台name node之间的元数据。具体做法:从第一台NN拷贝元数据到放到另一台NN,然后启动第一台的NameNode进程,再到另一台名称节点上做standby引导

2.1.4 把第一台名节点的edit日志初始化到JN节点,以供standby节点到JN节点拉取数据

2.1.5启动standby状态的名称节点,这样就能同步fsimage文件

2.1.6 模拟故障,手动把active状态的NN故障,转移到另一台NN

HDFS的运行原理,如何实现HDFS的高可用 

2.2如何通过自动容灾而不是手动容灾?

通过zookeeper实现。

自动容灾引入两个组件:zk quarum + zk容灾控制器。

运行NN的2台主机还要运行ZKFC进程(DFSZKFailoverController),主要负责: 健康监控、session管理、leader选举。

大概流程是:

2.2.7 在上面HA配置的基础上,要另外准备3台主机安装zookeeper,3台主机形成一个小的zk集群.

2.2.8 启动ZK集群每个节点上的QuorumPeerMain进程

2.2.9 登录其中一台NN, 在ZK中初始化HA状态

2.2.10 模拟故障:停掉活跃的NameNode进程,会发现自动切换active到另一台NN,模拟过程如下——

 

[centos@h201 current]$ xcall jps             # 查看HDFS集群的每个节点上运行哪些进程

----------执行jps 在主机h201

44992 DFSZKFailoverController

46624 Jps

44110 QuorumPeerMain

44686 NameNode

命令已成功执行!----------

 

----------执行jps 在主机h202

17521 Jps

17210 DataNode

17021 QuorumPeerMain

17310 JournalNode

命令已成功执行!----------

 

----------执行jps 在主机h203

15777 JournalNode

15988 Jps

15494 QuorumPeerMain

15677 DataNode

命令已成功执行!----------

 

----------执行jps 在主机h204

16516 DataNode

16616 JournalNode

16826 Jps

命令已成功执行!----------

 

----------执行jps 在主机h205

23170 DFSZKFailoverController

23844 Jps

23064 NameNode

命令已成功执行!----------

 

[centos@h201 hadoop]$ hdfs haadmin-getServiceState nn1          #h201是第一台NN

active

[centos@h201 hadoop]$ hdfs haadmin-getServiceState nn2          # h205是另一台NN

standby

[centos@h201 hadoop]$jps

44992 DFSZKFailoverController

44110 QuorumPeerMain

44686 NameNode

47326 Jps

[centos@h201 hadoop]$kill -9 44686         # 模拟nn1故障, DFSZKFailoverController自动把nn2激活

[centos@h201 hadoop]$ hdfs haadmin-getServiceState nn2

active

---------------------------------<全文完>------------------------------