本节书摘来异步社区《Hadoop技术详解》一书中的第2章,第2.6节,作者: 【美】Eric Sammer 译者: 刘敏 , 麦耀锋 , 李冀蕾 , 等,更多章节内容可以访问云栖社区“异步社区”公众号查看。
2.6 NameNode的高可用性
因为管理员的主要职责是确保大规模系统的服务质量和可用性,单点故障(single point of failure)可能会给我们带来麻烦,甚至带来非常糟糕的后果。不幸的是,长期以来,HDFS的NameNode就是困扰我们的单点故障问题。近来,Hadoop社区投入大量的人力来提升NameNode的高可用性,使Hadoop可以在更多重要应用场景下部署。
NameNode 高可用性(或称HA)是通过部署一对主/备NameNode的方式来实现的。主/备NameNode都需要能访问到edits的WAL,因此edits通常保存在一个共享的存储设备上。目前,是用NFS文件系统实现这种共享存储的,当然消除对NFS的依赖也已经在计划当中[2]。当主NameNode写入edits日志时,备用NameNode会即时重放事务以确保数据的完全同步,并在主NameNode发生故障时,随时接管它的工作。通过高可用性配置,集群中所有DataNode都知道主/备NameNode对的存在,它们会同时向这两台服务器发送块报告。
高可用性的主/备NameNodes对可以配置为手动或自动故障切换模式。在默认情况下,采用的是手动模式,需要用命令来触发NameNode状态的变更。当配置成自动模式时,这两个NameNode都会运行一个名为“切换控制器”的进程,来监管其他进程的状态并协调NameNode状态的变更。和其他高可用性系统一样,hadoop也有两种主要的故障切换模式:管理员主导的优雅故障切换模式(graceful failover)和由运行过程中发生的故障触发的非优雅故障切换模式(non-graceful failover)。然而,不管是哪一种模式,都很难确定主NameNode是否确实已经退出了活动状态,也许仅仅是因为备用NameNode访问不到它。这时,如果允许主、备NameNode进程同时工作,就有可能因同时写入共享文件而破坏文件系统的元数据,这一场景通常被称为脑裂(split brain)。因此,为了应对这样的情况,系统可以通过一系列严厉的手段来确保故障节点(可能还是活动的)真正停止工作。刚开始时可以用RPC来要求其停止工作,实在无效时可以使用“爆头”(Shoot The Other Node In The Head)技术,即通过IPMI 来重启机器。如果电源模块支持这项功能,甚至可以通过程控电源短时掉电的方式来完成。大部分管理员希望通过自动故障切换模式来实现系统的高可用性。图2-5所示为一个自动故障切换实例。
在高可用模式下,备用NameNode同时也会承担次NameNode的角色。也就是说,在HA集群中不会有单独的次NameNode进程,而只有一对NameNode进程。大多数情况下,已经通过专用主机部署次NameNode的Hadoop集群可以将该主机配置成备用NameNode。高可用性的不同配置选项可以参见5.6节“NameNode的高可用性”。
在写本书时,Apache Hadoop 2.0和CDH4已经支持NameNode的高可用性(简称NNHA)。
为什么不使用某个HA包?
熟悉Linux HA项目的用户可能会问:为什么不简单地写些脚本,像Linux HA那样解决HDFS NameNode高可用性的问题?虽然那些工具已经支持状态检测、带内/外
通信和保护插件等,但不幸的是,高可用性是个很复杂的问题,绝不仅仅是杀死一个进程而后在另一个地方重启一个新进程那么简单。
NameNode 高可靠性真正的挑战来自于DataNode—块报告只是写入NameNode内存而不是磁盘。换而言之,即便用这些系统搭建好一个集群、写入合适的健康检查报告、检测到错误、发起故障切换、激活备机,系统还是无法知道应该从哪儿找到数据块,仍然无法给HDFS客户端提供服务。当然,DataNodes或许可以通过一个虚拟IP(VIP)联系到NameNode,但它无法知道已经发生了故障切换,也无法向新NameNode发送块报告而使它快速获得集群最新状态。之前我们看到,接收和处理成百上千台DataNodes发送过来的块报告,实际上是集群启动过程中比较耗时的部分,需要数十分钟或更多的时间,而这种开销对于时间敏感的系统而言是无法接受的。
Linux-HA适合于无状态的业务处理类型,对于如NameNode的有状态业务是远远不够的。