为什么需要自动故障转移
在 HDFS 2.x 集群的 HA 模式下通常会有两个 NameNode 用来进行记录元数据,其中一个是主节点(Active),另外一个是备节点(Standby)。主备之间的数据同步通过 JournalNode 节点来充当中介,从而完成了主备节点之间数据的最终一致性。
当 NameNode 的主节点宕机后,通过命令可以切换到它的备节点成为主节点,使用命令进行切换需要人工的参与,虽然这样可以解决 HDFS 高可用的问题,但是这样的切换还是比较繁琐的。因此需要在 Active 节点发生故障的时候进行自动地切换到 Standby 节点,从而完成故障自动转移。
为了实现故障的自动转移,HDFS 引入了 ZooKeeper 和 ZKFC。
故障自动转移
HDFS 为了实现故障自动转移功能添加了两个组件,分别是 ZooKeeper 集群
和 ZKFailoverController 进程。其中,ZKFailoverController 简称为 ZKFC。
ZooKeeper 在故障自动转移中的作用大体有两个,第一个是 NameNode 的选“主”,第二个是监听故障的发生。
ZKFC 在故障自动转移中的作用大体也是两个,第一个是在 ZooKeeper 中用于争抢锁完成选“主”,第二个是当 Active 节点发生故障时,用于完成故障的自动切换。
HDFS HA 故障自动转移架构图
来看一下 HDFS HA 故障自动转移架构图。在图中,非蓝色部分是 HDFS 的 HA 模式,蓝色部分则完成了故障自动转移的功能,即当 Active 节点发生故障时,会自动切换 Standby 节点为 Active 节点。
本图和上篇文章 《HDFS 在 HA 模式集群下 JournalNode 节点的作用》 的图稍微有所差别。首先,ZooKeeper 集群的节点是单数节点,上篇文章的图中 ZooKeeper 画了四台;第二,ZKFC 和 NameNode 在同一台主机中,因此把它们框在了一起。
NameNode 如何选主
在了解 ZKFC 如何完成自动切换前,需要了解 NameNode 如何进行选主。NameNode 节点的选主是一件比较容易的事情,ZKFC 会在 ZooKeeper 下创建一个”临时节点“,哪个 ZKFC 先创建了该节点,那么创建了该节点的 ZKFC 对应的 NameNode 就是主节点(Active)。没有创建成功的 ZKFC 对应的 NameNode 即为备节点(Standby)。NameNode 选主是争抢制,无需选举,谁抢上就是谁的。
ZKFC 完成故障自动转移
两个 ZKFC 通过争抢在 ZooKeeper 中创建锁,创建成功的即为”主“,那么没有创建的成功的 ZKFC 会创建一个监听事件。当”主“发生宕机或断网后,锁会被自动删除,此时 ZooKeeper 会通知备节点的 ZKFC。当备节点的 ZKFC 接收该通知时,就会开始做故障自动转移的工作。
一般主发生故障会有几种情况。首先,主 NameNode 服务挂了,这时它对应的 ZKFC 会主动删除 ZooKeeper 中的锁;第二种情况是,主 NameNode 对应的 ZKFC 挂了(但是 NameNode 健在),那么它在 ZooKeeper 中创建的临时节点也会被删除;还有第三种情况是,主 NameNode 所在的主机断网了。
上面说了产生故障的可能性,那么来说下一故障转移的大体流程。首先来说,主 NameNode 服务挂掉后的故障转移,大致流程如下:
首先,主节点对应的 ZKFC 发现主 NameNode 服务挂掉了,那么它会主动去 ZooKeeper 中删除锁。然后,备节点对应的 ZKFC 收到通知后会去创建锁;接着,备节点的 ZKFC 会去看一下主节点的 NameNode,此时发现主节点的 NameNode 已经不活着了;最后,备节点的 ZKFC 会把备节点的 NameNode 提升为主节点。
第二种情况是,主节点的 NameNode 服务还存在,但是它对应的 ZFKC 进程挂掉了。当 ZKFC 进程挂掉后,它在 ZooKeeper 中创建的临时节点会自动删除。然后,备节点对应的 ZKFC 收到通知还是去会争抢锁;接着,它会去看看主节点的 NameNode,发现主节点的 NameNode 还在,此时它会让主节点的 NameNode 降级成为从节点;最后,会把原来的备节点的 NameNode 提升为主节点。
总结
通过三篇文章,整列了关于 HDFS 的几个技术点,分别是 HDFS 元数据的持久化,HDFS 主备节点之间如何完成数据一致性,还有本篇文章整理的 ZKFC 完成故障自动转移。三篇文章均没有涉及任何配置、命令和原理。只是讲其中的思想、流程等进行了介绍。
通过几篇文章,联系自己已有的一些技术知识会发现,很多技术都是相通的。比如 HDFS 元数据的持久化是通过 FsImage 和 EditsLog 来完成的,而 FsImage 和 EditsLog 的原理和 Redis 的 RDB 和 AOF 又非常相似。而 JournalNode 完成数据的最终一致性,其实对于其他技术中主备完成数据一致性来说也是相似的。
很多 API 的使用,基本可能是学一个会一个,而原理则可能是一通百通。把知识的相关性不断的联系起来,可能解决问题,学习新知识就会越来越快了。