NameNode的选举机制

219 阅读3分钟

开启掘金成长之旅!这是我参与「掘金日新计划 · 2 月更文挑战」的第 7 天,点击查看活动详情

NameNode的选举机制

需求是什么?

为了解决大规模海量小文件带来的内存增长压力,所以需要设计 NameNode 的联邦架构,简单来说,就是通过多个NameNode节点组成集群,每个NameNode节点保存整个内存目录树的一部分数据。

这里需要和 Hadoop 中的 NameNode 的联邦架构做出区别:

在Hadoop HDFS联邦环境中,每个NameNode都保存一份完整的元数据,包括文件系统的目录结构、文件的副本信息以及每个副本所在的DataNode。

联邦机制通过同步这些数据来确保所有的NameNode都有完整的元数据。当任何一个NameNode上的数据更改时,它将同步这些更改到其他所有的NameNode上,以确保所有NameNode上的数据保持一致。

因此,在联邦环境中,每个NameNode都保存完整的元数据,这是为了确保整个文件系统的正常工作,以及在任何一个NameNode停止工作时,任何可用的NameNode都可以提供服务。

Hadoop 中的联邦机制是为了解决单点故障问题,而我们这里的联邦机制是为了解决大规模海量小文件带来的内存增长压力。

具体设计

分片程序的引入

1.分片程序启动前模式判断: 只有集群模式下才可以启动分片程序。

        // 如果是单机模式(与集群模式相对),则直接返回
        // 单机模式不需要分片
        if (NameNodeLaunchMode.SINGLE.equals(nameNodeConfig.getMode())) {
            return;
        }

2.集群模式下单结点判断: 集群模式下,可以分为两种情况:一种是只有一个结点,一种是有多个结点。

单节点的情况:单节点自己就是主节点了,所以它是不需要等待连接的,可以直接开始选举。

if (nameNodeConfig.getNameNodePeerServers() == null || nameNodeConfig.getNameNodePeerServers().length() == 0
        || nameNodeConfig.getNameNodePeerServers().split(",").length == 1) {

    log.info("NameNode集群模式为单点模式, 自己就是 Controller 节点");
    // 启动 Controller选举
    controllerManager.startControllerElection();
}

多节点的情况:多节点的话,则需要连接并记录相关结点信息,最后才能开始选举。

else {
    String nameNodePeerServers = nameNodeConfig.getNameNodePeerServers();
    String[] nodeServer = nameNodePeerServers.split(",");
    for (String server : nodeServer) {
        // 为客户端添加 PeerNode: 主动连接 NameNode 节点
        // 新来的 NameNode 在启动时,主动连接其他 NameNode ?
        peerNameNodes.connect(server);
    }

选举过程

投票记录: 记录投票投给谁了(不需要记录是谁投的,因为有影响的是谁得到了投票,而不是谁投的)

// 记录了投票给谁
// 记录了所有投票者所投给的候选者
// {A,A,A,B,C} 最终可以经过计算得到 A结点是3票,超过半数
private List<ControllerVote> voteList = new ArrayList<>();

真正开始选举的时机: 待所有结点都投票后才开始选举(即畅票)

// 循环选举,直到选举出来为止
while (true) {
   // 为什么需要等待?
   // 当 voteList.size() == numOfNode.get() 时,说明所有节点都投票完成
   // 只有所有节点都投票完成才进行下一步,否则等待。
   if (voteList.size() != numOfNode.get()) {
      synchronized (this) {
         wait(10);
      }
   }
   ......