HDFS中NameNode 单点失败的改进案例介绍

时间:2024-11-15 22:06:11

Hadoop的使用中,NameNode的单点失败问题一直困扰着框架的使用者。这一节我们提出了一种利用ZooKeeper对NameNode进行冗余备份协同工作方案,避免了NameNode单点失败造成的服务不可用与文件丢失问题。

NameNode是整个HDFS的核心,HDFS所有的操作均需由NameNode参与,并且NameNode负责维护整个分布式文件系统中所有文件的元信息以及目录信息。如果NameNode出现了失败,那么HDFS中所有文件信息将全部丢失。虽然HDFS针对每一个文件都可以根据配置进行多份数据备份,但是NameNode却只有一个。这使得NameNode成为了HDFS中的薄弱点,如果NameNode发生单点失败将导致整个HDFS系统的失败。

图1-9NameNode架构图

HDFS中使用SecondaryNameNode解决NameNode失败的问题。SecondaryNameNode并不是NameNode的冗余备份,而是单独的一个参与者,负责对NameNode中文件元信息以及文件结构定期快照。SecondaryNameNode定期从NameNode上下载镜像和日志进行合并,称为一次checkpoint,将得到的新的镜像文件上传到NameNode替换原来的镜像文件,使得NameNode上的镜像文件保持最新。当NameNode出现失败时,可以从SecondaryNameNode所在的机器拷贝之前的快照,然后重启NameNode,此时NameNode会导入快照中保存的文件信息,重建文件系统。

SecondaryNameNode方案存在以下几个问题:

1.必须通过人工的方式寻找并拷贝SecondaryNameNode中保存的快照文件,手工重启NameNode,无法自动化完成。

2.在NameNode失败期间,任何人都无法面对HDFS中的文件进行任何形式的访问,系统失败的时间取决于人工恢复NameNode的时间。

是以文件镜像(fsimage)和操作日志(edit)方式存储HDFS中文件元信息和目录结构的,其中edit是实时日志信息,每过一段时间(默认1小时)或当操作日志文件大小增加到一定规模时(默认64MB)由SecondaryNameNode负责将edit合并到文件镜像中并备份。如果NameNode发生失败而由SecondaryNameNode中快照恢复的话,会导致尚处在操作日志中未被合并的文件操作信息完全丢失,从而导致文件丢失。

为了解决NameNode单点失败造成的问题,改进的HDFS系统中可配置多个NameNode,每个NameNode与所有的DataNode均有联系,且向ZooKeeper注册自己的存在(在特定的ZNode下创建临时性ZNode,并将自身信息保存在对应ZNode中)。与此同时,架构中加入一个角色Dispatcher,负责将读、写请求传递给活跃的NameNode执行、处理多个NameNode的同步以及互斥问题,并根据ZooKeeper提供的信息监控NameNode的健康情况以确保当某个NameNode发生失败后将其从“活跃的”NameNode列表中去除。


图1-10改进后的HDFS系统架构图

改进后的HDFS系统包括读流程和写流程两个部分,其中读流程如下:

1.用户发起一个读文件请求;

收到读请求,检查ZooKeeper中的InWriting列表,如果在InWriting列表中则等待,否则将读请求加入InReading列表中。

3.从ZooKeeper中寻找活跃的NameNode,将此读请求转发给对应的NameNode并记录。

收到读请求后处理,将处理结果交由Dispatcher并反馈给用户。Dispatcher从InReading列表中删除对应请求。

5.如果Namenode长时间未响应或者读请求失败,由Dispatcher寻找另外的Namenode,转第3步。

写文件流的流程如下:

1.用户发起一个写文件请求。

收到写请求,检查ZooKeeper中的InWriting和InReading列表,如果在列表中则等待,否则将写请求加入InWriting列表中。

3.从ZooKeeper中寻找活跃的NameNode,将此写请邱转发给对应的NameNode并记录。

收到写请求后处理,如果写操作成功,则通知Dispatcher。Dispatcher告知其他NameNode此次写操作细节,其他NameNode做对应更新。

5.所有NameNode均更新完毕后,Dispatcher从InWriting中移除对应请求,并返回给用户。

6.如果NameNode长时间未响应或者写请求失败,由Dispatcher寻找另外的NameNode,转第3步。

当某一个NameNode失败时,ZooKeeper中对应的临时性ZNode会自动消失,而Dispatcher在得知此事件后,可以将其从活跃NameNode中去除,对于已经分配给此NameNode且尚未处理完成的读写请求可以重新分配。而对于后续的读写请求,Dispatcher则交给仍然活跃的NameNode进行处理,对于用户来说是透明的。

改进后的HDFS系统中Dispatcher变成了单点,依旧存在失败的风险。但Dispatcher失败的可能性与危害都远远小于NameNode失败。原因有以下几点:

1.为了维护HDFS系统中的文件源信息以及目录结构,NameNode需要将所有数据全部载入内存,这使得当文件系统足够庞大时NameNode需要消耗很多的内存,这无疑增加了失败的可能性。而Dispatcher的任务相对较轻,仅仅是作为一个中转站转发读写请求,失败的可能性较小。

自身不保存任何数据。所有的数据完全交由ZooKeeper存储,而ZooKeeper自身的特性保证了其很难出现失败。即使Dispatcher失败,也可以重新启动并根据ZooKeeper中记录的信息完全恢复。

3.作为一个成熟的分布式文件系统,对文件安全性与完整性的保证是十分重要的。如果是单NameNode,不管SecondaryNameNode备份间隔如何缩短,在上一次备份到系统失败这段时间内的文件操作便会全部丢失,这有可能给系统的使用者带来不可挽回的损失。而改进后的系统不存在这个问题,如果一个修改操作成功,则会被保存在所有NameNode上,丢失文件的机会很小。

所以,相对于只有一个NameNode的HDFS系统,改进后的HDFS系统具有很强的安全性。当一个NameNode失败后,使用活跃的NameNode中拷贝过来的fsimage和edit文件作为恢复用途。在添加或恢复一个NameNode之前,先向ZooKeeper注册一个“备用的”NameNode节点,而Dispatcher在发现有此类节点时则将之后所有的成功写请求保存在ZooKeeper上。当新添加的NameNode使用fsimage和edit文件恢复完成后,在Dispatcher再将记录的写请求按照顺序发送给此NameNode,此NameNode根据这一信息同步文件元信息及目录结构。当新的NameNode同步完成时,删除ZooKeeper中备用NameNode节点,添加正式的NameNode临时节点。此事Dispatcher便可得知系统中新NameNode的存在并使用。



欢迎关注麦克叔叔每晚十点说,有兴趣的朋友可关注公众号,让我们一起交流,一起学习。