第七章:小朱笔记hadoop之源码分析-hdfs分析 第四节:namenode分析-format过程分析

第七章:小朱笔记hadoop之源码分析-hdfs分析

第四节:namenode分析

 4.2 namenode format过程分析

       namenode format操作是使用hadoop分布式文件系统前的步骤。如果不执行这个步骤,无法正确启动分布式文件系统。

(1)启动format

 start-dfs.sh的脚本分析过程,传入的-format参数传入到执行类,namenode对应的执行类是org.apache.hadoop.hdfs.server.namenode.NameNode。

(2)执行NameNode.format格式化hdfs操作

 这个过程是整个format的流程的主要部分,里面设计到FSNamesystem和FSImage两个和hdfs文件系统关系密切的类。

 

    //通过配置文件配置参数获取fsimage文件所存放的目录,本文后面的部分会单独介绍fsimage文件  
    Collection<File> dirsToFormat = FSNamesystem.getNamespaceDirs(conf);  
    //通过配置文件配置参数获取edits文件所存放的目录,本文后面的部分会单独介绍edits文件  
    Collection<File> editDirsToFormat =FSNamesystem.getNamespaceEditsDirs(conf);  

 对fsimage目录进行校验,如果已存在,需要用户确认是否要格式化,如果不允许格式化,则退出。

(3)FSImage.format

 初始化系统的基本信息,包括版本信息,文件系统的编号等,调用clearDirectory完全删除sd所在的目录,然后再创建空目录,调用saveCurrent创建sd目录下的current目录和fsimage目录及相关文件。
 注意: 生成NameSpaceID的算法.

 

    /** Create new dfs name directory.  Caution: this destroys all files 
      * in this filesystem. */  
     void format(StorageDirectory sd) throws IOException {  
       sd.clearDirectory(); // 创建currrent目录,如果该目录存在,则会删除存在的current目录树    
       sd.lock(); // 加锁,对应的文件为in_use.lock  ;  
       try {  
         saveCurrent(sd);  
       } finally {  
         sd.unlock();  
       }  
       LOG.info("Storage directory " + sd.getRoot()  
                + " has been successfully formatted.");  
     }  
      
     public void format() throws IOException {  
       this.layoutVersion = FSConstants.LAYOUT_VERSION;  
       this.namespaceID = newNamespaceID();  
       this.cTime = 0L;  
       this.checkpointTime = FSNamesystem.now();  
       for (Iterator<StorageDirectory> it =   
                              dirIterator(); it.hasNext();) {  
         StorageDirectory sd = it.next();  
         format(sd);  
       }  
     }  
      
     /** 
      * Generate new namespaceID. 
      *  
      * namespaceID is a persistent attribute of the namespace. 
      * It is generated when the namenode is formatted and remains the same 
      * during the life cycle of the namenode. 
      * When a datanodes register they receive it as the registrationID, 
      * which is checked every time the datanode is communicating with the  
      * namenode. Datanodes that do not 'know' the namespaceID are rejected. 
      *  
      * @return new namespaceID 
      */  
     private int newNamespaceID() {  
       Random r = new Random();  
       r.setSeed(FSNamesystem.now());  
       int newID = 0;  
       while(newID == 0)  
         newID = r.nextInt(0x7FFFFFFF);  // use 31 bits only  
       return newID;  
     }  

 

(4)saveCurrent(sd)过程分析

    protected void saveCurrent(StorageDirectory sd) throws IOException {  
      File curDir = sd.getCurrentDir();  
      NameNodeDirType dirType = (NameNodeDirType)sd.getStorageDirType();  
      // save new image or new edits  
      if (!curDir.exists() && !curDir.mkdir())  
        throw new IOException("Cannot create directory " + curDir);  
      if (dirType.isOfType(NameNodeDirType.IMAGE)) // 如果是fsimage目录    
        saveFSImage(getImageFile(sd, NameNodeFile.IMAGE)); // 保存fsimage映像    
      if (dirType.isOfType(NameNodeDirType.EDITS)) // 如果是edits日志文件目录    
        editLog.createEditLogFile(getImageFile(sd, NameNodeFile.EDITS)); // 创建一个新的edits文件    
      sd.write(); // 写版本文件VERSION    
      //写入支持旧版本的fsimage目录内容、写入版本信息到VERSION文件中、写入当前系统时间到fstime目录中  
      
    }  

 

        类FSImage初始化成员变量后,会遍历所有的元数据存储目录,以存储目录作为参数,依次调用format方法,format方法采用了重载的方 式,可以根据输入参数的个数和类型确定所调用的方法,此处调用的方法为format(StorageDirectory sd)。该方法首先调用"sd.clearDirectory();"删除当前存储目录下[配置的fsimage路径(edits路 径)/current]的所有内容;然后对传入的目录类型进行判断,如果是存储FSImage文件的目录,则调用saveFSImage保存FSImage,如果是存储Edits日志文件的目录,则调用editLog.createEditLogFile,在该目录下创建Edits文件;最后调用sd.write()方法在存储目录下创建fstime和VERSION文件,VERSION通常是在存储目录更新的最后写 入,VERSION的存在表明存储目录下其他的文件已成功写入,因此该存储目录有效无需恢复,VERSION文件的内容为:layoutVersion、 storageType、namespaceID、cTime。

 

 

猜你喜欢

转载自huashuizhuhui.iteye.com/blog/1871716