hadoop namenode深度剖析

来源:互联网 发布:小米电视怎么样 知乎 编辑:程序博客网 时间:2024/06/08 17:41

1、NAMENODE内部结构(fsimage+edits+blockmap)
     fsimage:保存了最新的元数据检查点;
     edits:保存了HDFS中自最新的元数据检查点后的命名空间变化记录;

     BlockMap: 在fsimage中,并没有记录每一个block对应到哪几个datanodes的对应表信息,而只是存储了所有的关于namespace的相关信息。而真正每个block对应到datanodes列表的信息在hadoop中并没有进行持久化存储,而是在所有datanode启动时,每个datanode对本地磁盘进行扫描,将本datanode上保存的block信息汇报给namenode,namenode在接收到每个datanode的块信息汇报后,将接收到的块信息,以及其所在的datanode信息等保存在内存中。HDFS就是通过这种块信息汇报的方式来完成 block -> datanodes list的对应表构建。Datanode向namenode汇报块信息的过程叫做blockReport,而namenode将block -> datanodes list的对应表信息保存在一个叫BlocksMap数据结构中。

 

为防止edits中保存的最新变更记录过大,standby nn会定期合并fsimage和edits文件形成新的fsimage文件,然后重新记录edits文件。

Fsimage是一个二进制文件,它记录了HDFS中所有文件和目录的元数据信息。关于fsimage的内部结构我们可以参看下图:
fsimage

第一行是文件系统元数据,第二行是目录的元数据信息,第三行是文件的元数据信息。

NameNode将这些信息读入内存之后,构造一个文件目录结构树,将表示文件或目录的节点填入到结构中。
在NameNode加载fsimage完成之后,BlocksMap中只有每个block到其所属的datanodes list的对应关系信息还没建立。然后通过dn的blockReport来收集构建。当所有的DataNode汇报给NameNode的blockReport处理完毕后,BlocksMap整个结构也就构建完成了。

     文件和block的映射,固化在磁盘上。而block和DataNode的映射在DataNode启动时上报给NameNode

      以上内容来自: http://blog.csdn.net/yy10992/article/details/50081783
2、NAMENODE HA

dfs.namenode.edits.dir (NameNode 编辑目录) :  写入 NameNode 编辑的本地文件系统上的目录。未指定将存放在namenode数据目录中。
dfs.journalnode.edits.dir (JournalNode 编辑目录):用于存储 NameNode 编辑的本地文件系统目录。journalnode所在节点的目录,存放editlog和其他信息。
dfs.namenode.shared.edits.dir (共享编辑目录):用于存储 NameNode 编辑的共享存储设备上的目录,例如基于 Quorum 的存储 URI 或 NAS 上的 NFS 装载的本地目录。
<property>
  <name>dfs.namenode.shared.edits.dir</name>
  <value>qjournal://master:8485;slave1:8485;slave2:8485/hadoop-journal</value>
</property>
多个NN数据同步通过NFS或QJM的方式进行,NFS是操作系统层面的配置,而QJM是hadoop自带的软件配置,一般用的较多的是QJM配置。
同一时间只有一个namenode可往JNS的中写数据。
为了让Standby Node与Active Node保持同步,这两个Node都与一组称为JNS的互相独立的进程保持通信(Journal Nodes)。当Active Node上更新了namespace,它将记录修改日志发送给JNS的多数派。Standby noes将会从JNS中读取这些edits,并持续关注它们对日志的变更。Standby Node将日志变更应用在自己的namespace中,当failover发生时,Standby将会在提升自己为Active之前,确保能够从JNS中读取所有的edits;即在failover发生之前,Standy持有的namespace应该与Active保持完全同步。
在standby NameNode节点上会一直运行一个叫做CheckpointerThread的线程,这个线程调用StandbyCheckpointer类的doWork()函数,而doWork函数会每隔Math.min(checkpointCheckPeriod, checkpointPeriod)秒来坐一次合并操作,相关代码如下:

    try {
              Thread.sleep(1000 * checkpointConf.getCheckPeriod());
            } catch (InterruptedException ie) {
    }

    public long getCheckPeriod() {
        return Math.min(checkpointCheckPeriod, checkpointPeriod);
    }

    checkpointCheckPeriod = conf.getLong(
            DFS_NAMENODE_CHECKPOINT_CHECK_PERIOD_KEY,
            DFS_NAMENODE_CHECKPOINT_CHECK_PERIOD_DEFAULT);
            
    checkpointPeriod = conf.getLong(DFS_NAMENODE_CHECKPOINT_PERIOD_KEY,
                                    DFS_NAMENODE_CHECKPOINT_PERIOD_DEFAULT);
 


上面的checkpointCheckPeriod和checkpointPeriod变量是通过获取hdfs-site.xml以下两个属性的值得到:

    <property>
      <name>dfs.namenode.checkpoint.period</name>
      <value>3600</value>
      <description>The number of seconds between two periodic checkpoints.
      </description>
    </property>

    <property>
      <name>dfs.namenode.checkpoint.check.period</name>
      <value>60</value>
      <description>The SecondaryNameNode and CheckpointNode will poll the NameNode
      every 'dfs.namenode.checkpoint.check.period' seconds to query the number
      of uncheckpointed transactions.
      </description>
    </property>

 
当达到下面两个条件的情况下,将会执行一次checkpoint:

    boolean needCheckpoint = false;
    if (uncheckpointed >= checkpointConf.getTxnCount()) {
         LOG.info("Triggering checkpoint because there have been " +
                    uncheckpointed + " txns since the last checkpoint, which " +
                    "exceeds the configured threshold " +
                    checkpointConf.getTxnCount());
         needCheckpoint = true;
    } else if (secsSinceLast >= checkpointConf.getPeriod()) {
         LOG.info("Triggering checkpoint because it has been " +
                secsSinceLast + " seconds since the last checkpoint, which " +
                 "exceeds the configured interval " + checkpointConf.getPeriod());
         needCheckpoint = true;
    }

 
 当上述needCheckpoint被设置成true的时候,StandbyCheckpointer类的doWork()函数将会调用doCheckpoint()函数正式处理checkpoint。当fsimage和edits的合并完成之后,它将会把合并后的fsimage上传到Active NameNode节点上,Active NameNode节点下载完合并后的fsimage,再将旧的fsimage删掉(Active NameNode上的)同时清除旧的edits文件。步骤可以归类如下:
  (1)、配置好HA后,客户端所有的更新操作将会写到JournalNodes节点的共享目录中,可以通过下面配置


    <property>
      <name>dfs.namenode.shared.edits.dir</name>
      <value>qjournal://XXXX/mycluster</value>
    </property>

    <property>
      <name>dfs.journalnode.edits.dir</name>
      <value>/export1/hadoop2x/dfs/journal</value>
    </property>

 

(2)、Active Namenode和Standby NameNode从JournalNodes的edits共享目录中同步edits到自己edits目录中;
  (3)、Standby NameNode中的StandbyCheckpointer类会定期的检查合并的条件是否成立,如果成立会合并fsimage和edits文件;
  (4)、Standby NameNode中的StandbyCheckpointer类合并完之后,将合并之后的fsimage上传到Active NameNode相应目录中;
  (5)、Active NameNode接到最新的fsimage文件之后,将旧的fsimage和edits文件清理掉;
  (6)、通过上面的几步,fsimage和edits文件就完成了合并,由于HA机制,会使得Standby NameNode和Active NameNode都拥有最新的fsimage和edits文件(之前Hadoop 1.x的SecondaryNameNode中的fsimage和edits不是最新的)
JournalNode服务器:运行的JournalNode进程非常轻量,可以部署在其他的服务器上。注意:必须允许至少3个节点。当然可以运行更多,但是必须是奇数个,如3、5、7、9个等等。当运行N个节点时,系统可以容忍至少(N-1)/2(N至少为3)个节点失败而不影响正常运行。
dfs.ha.automatic-failover.enabled:启动自动failover,依赖于zookeeper集群和ZKFailoverController(ZKFC)
ZKFailoverController: ZK客户端用来监控namenode的状态。每个运行nn的节点必须要运行一个zkfc。
zkfc提供以下功能:
health monitor: zkfc定期对本地nn发起health检查,如正确返回,则认为NN正常,否则被认为失效节点。
session management: 当本地NN正常时,ZKFC会在zk中注册一个session,如果该NN是ACTIVE状态,还会持ephemeral节点作为锁;一旦NN不正常,则该session会自动删除。
active选举: 当本地NN正常时,且没有其他的NN持有独占锁,ZKFC会去获得锁,一旦成功,就需要执行Failover(对之前的NN进行隔离,再将本地NN转换到Active状态),然后成为active的NN节点。

为了确保快速切换,standby状态的NameNode有必要知道集群中所有数据块的位置。为了做到这点,所有的datanodes必须配置两个NameNode的地址,发送数据块位置信息和心跳给他们两个。
hdfs haadmin -transitionToActive nn1 :将指定的namenode ID切换为Active或者standby
hdfs haadmin -DFSHAAdmin -failover nn1 nn2 :在两个Namenode之间failover。这个指令会触发将first节点failover到second节点。如果first处于standby,那么只是简单的将second提升为Active。如果first为Active,那么将会友好的将其切换为standby,如果失败,那么fencing methods将会触发直到成功,此后second将会提升为Active。如果fencing method失败,那么second将不会被提升为Active。
FAQ:
1、如果Zookeeper失效,将会怎么样?
如果zookeeper集群故障,那么Automatic Failover将不会触发,即使Namenode失效,这也意味着ZKFC无法正常运行。不过,如果Namenodes正常(即使有一个失效),那么HDFS系统将不会受到影响。因为HDFS Client并没有基于zookeeper做任何事情,当zookeeper集群仍需要尽快的恢复以避免当前Active失效而造成的“split-brain”等问题。
2、是否可以在Namenodes之间指定优先级?
NO,这是不能支持的。首先启动的Namenode将作为Active,我们只能认为控制Namenode启动的顺序来做到“优先级”。
3、在Automatic Failover中,手动Failover怎么做?
和普通的Failover一样,我们总是可以通过"hdfs haadmin -DFSHAAdmin -failover"来实现手动Failover。



以上内容摘自:

http://blog.csdn.net/zh521zh/article/details/51788901

http://blog.csdn.net/shift_alt_ctrl/article/details/69944390