HDFS的NameNode使用主备架构实现高可用,主备选举通过zookeeper作协调器实现。选举由zkfc组件(zkfc与NameNode同一台机器,属于两个不同的进程)发起,选主流程:会尝试在 Zookeeper上创建一个路径为/hadoop-ha/${dfs.nameservices}/ActiveStandbyElectorLock 的临时节点,Zookeeper 的写一致性会保证最终只会有一个zkfc组件创建成功而成为主NameNode。
触发主备选举
如果zkfc组件检测到 NameNode 的状态异常时,会主动删除当前在 Zookeeper 上建立的临时节点/hadoop-ha/${dfs.nameservices}/ActiveStandbyElectorLock,这样处于备状态的NameNode的zkfc组件监听器就会收到这个节点的 NodeDeleted 事件。收到这个事件之后,会马上进入选主流程(文章开始处介绍)。
如果处于主NameNode所在的机器整个宕掉的话,那么根据 Zookeeper 的临时节点特性,/hadoop-ha/${dfs.nameservices}/ActiveStandbyElectorLock节点会自动被删除,从而也会自动进行一次主备选举切换。
但如果主NameNode所在机器因负载过高、系统线程调度、IO hang又或是常见的Full GC导致的长时间STW,都可能导致出现工程实践中常见的进程”假死“,如果”假死“时间过长,超过zookeeper session timeout,会触发/hadoop-ha/${dfs.nameservices}/ActiveStandbyElectorLock 的临时节点的删除,再次进入选主流程选出新主。这时如果原来的主NameNode突然恢复,可能会在接下来的一段时间内还认为自己还是主,可以对外提供服务,这样就出现多主,这就产生所谓的”脑裂“,这种情况对于数据一致性要求非常高的系统来说是灾难性的,导致数据错乱而无法恢复。HDFS的解决方案是fencing,即把旧的主通过某种手段隔离起来,使其不能对外提供服务。
fencing方案
HDFS的fencing实现是这样的,成功创建hadoop-ha/ d f s . n a m e s e r v i c e s / A