1. 程式人生 > >跟我一起讀Hadoop原始碼——HDFS篇(01)

跟我一起讀Hadoop原始碼——HDFS篇(01)

寫在前面的話

這裡是跟我一起讀Hadoop原始碼系列的第一篇,主要記錄作者在讀Hadoop原始碼的過程

軟體版本

-Hadoop2.6.0

讀前知識

-瞭解RPC程式設計
-瞭解Java基礎

從NameNode開始

在Hadoop的所有文章中都講述了Namenode的作用,所以這裡就不做過多的說明,直接
來讀它的原始碼。
在讀一個類時從哪裡下手比較好呢,當然是註釋。在大多開源軟體的主要程式碼中都會
給出比較詳細的註釋我們就從這裡入手。

/**********************************************************
 * NameNode serves as both directory namespace manager and
 * "inode table" for the Hadoop DFS.  There is a single NameNode
 * running in any DFS deployment.  (Well, except when there
 * is a second backup/failover NameNode, or when using federated NameNodes.)
 *
 * The NameNode controls two critical tables:
 *   1)  filename->blocksequence (namespace)
 *   2)  block->machinelist ("inodes")
 *
 * The first table is stored on disk and is very precious.
 * The second table is rebuilt every time the NameNode comes up.
 *
 * 'NameNode' refers to both this class as well as the 'NameNode server'.
 * The 'FSNamesystem' class actually performs most of the filesystem
 * management.  The majority of the 'NameNode' class itself is concerned
 * with exposing the IPC interface and the HTTP server to the outside world,
 * plus some configuration management.
 *
 * NameNode implements the
 * {@link org.apache.hadoop.hdfs.protocol.ClientProtocol} interface, which
 * allows clients to ask for DFS services.
 * {@link org.apache.hadoop.hdfs.protocol.ClientProtocol} is not designed for
 * direct use by authors of DFS client code.  End-users should instead use the
 * {@link org.apache.hadoop.fs.FileSystem} class.
 *
 * NameNode also implements the
 * {@link org.apache.hadoop.hdfs.server.protocol.DatanodeProtocol} interface,
 * used by DataNodes that actually store DFS data blocks.  These
 * methods are invoked repeatedly and automatically by all the
 * DataNodes in a DFS deployment.
 *
 * NameNode also implements the
 * {@link org.apache.hadoop.hdfs.server.protocol.NamenodeProtocol} interface,
 * used by secondary namenodes or rebalancing processes to get partial
 * NameNode state, for example partial blocksMap etc.
 **********************************************************/

這段註釋說明了NameNode的用途和實現的功能,本人英文不好在這裡就不翻譯了。

下面來看一下NameNode類的定義:

  @InterfaceAudience.Private
  public class NameNode implements NameNodeStatusMXBean {
    //些處省略類體定義

  }

O-O不是說好的實現了那麼多介面嗎,怎麼就實現了一個介面,是不是有介面繼承那再來看一
下這個介面的內容吧:

/**
 * This is the JMX management interface for NameNode status information
 * 這是一個被JMX管理的介面來監控NameNode的狀態
 */
@InterfaceAudience.Public @InterfaceStability.Evolving public interface NameNodeStatusMXBean { /** * Gets the NameNode role. * 獲取NameNode的角色 * 角色分為 NAMENODE("NameNode"),BACKUP("Backup Node"),CHECKPOINT("Checkpoint Node"); * @return the NameNode role. */ public String getNNRole(); /** * Gets the NameNode state. * 獲取NameNode的狀態這個是對HA來說的 * 可以有initializing,active,standby和stopping * @return
the NameNode state. */
public String getState(); /** * Gets the host and port colon separated. * 獲取NameNode的IP和埠號(localhost:9000) * @return host and port colon separated. */ public String getHostAndPort(); /** * Gets if security is enabled. * 獲取是否開啟了安全驗證 * @return true, if security is enabled. */ public boolean isSecurityEnabled(); }

木有,那它是怎麼實現上面所說的方法呢。來看看它的成員變數吧!

需要說明的是在Java中類實現某個功能可以通過繼承或者組合的方法
來實現

  //NameNode核心成員變數用來管理元資料
  protected FSNamesystem namesystem; 
  //儲存配置檔案的資訊
  protected final Configuration conf;
  //儲存NameNode的角色資訊
  protected final NamenodeRole role;
  //儲存NameNode的狀態
  private volatile HAState state;
  //是否開啟了高可用(HA)
  private final boolean haEnabled;
  //高可用上下文
  private final HAContext haContext;
  //NameNode核心成員變數提供RPC服務
  private NameNodeRpcServer rpcServer;

這裡只是簡單列出了幾個比較重要的成員變數來做分析,其它的有興趣可以自己閱讀原始碼
其中namesystem和rpcServer是核心成員,NameNode的大部分功能都由這兩個成員變數實現
namesystem:實現對DataNode、Block的管理以及讀寫日誌
rpcServer:提供RPC服務是DataNode和NameNode通訊和外部命令管理NameNode的視窗
以上兩個成員變數的分析將另開文章
conf:儲存NameNode的配置資訊,NameNode會根據這些資訊來初始化自己並開始執行

主要來自hdfs-site.xml

role:儲存當前NameNode的角色NAMENODE提供元資料管理的服務,BACKUP提供一個備用的NameNode並且
提供合併fsimage和edits的功能不同的是不用從NAMENODE下載(它本身的狀態和NAMENODE一致)
CHECKPOINT用來替代SecondNameNode的用來合併fsimage和edits

NameNode除了在叢集執行時提供管理叢集和元資料的功能外還提供以下功能
-FORMAT:格式化HDFS檔案系統
-GENCLUSTERID: 生成一個新的叢集ID
-FINALIZE:定版本,在升級完成並且通過測試後執行這個命令(這個命令被hdfs dfsadmin -finalizeUpgrade代替了)
-ROLLBACK:返回升級前的版本(注意:需要御載新版本並安裝老版本)
-BOOTSTRAPSTANDBY:同步active節點的快照(配置完HA需要執行這個命令)
-INITIALIZESHAREDEDITS:向備用節點共享一組edits日誌
-BACKUP:以BACKUP的角色啟動
-CHECKPOINT:以CHECKPOINT的角色啟動
-RECOVER:覆蓋元資料
-METADATAVERSION:驗證配置的正確性並列印版本資訊
-UPGRADEONLY:以升級的方式啟動
-Default:正常以NAMENODE啟動

以上命令在Hadoop的文件中都有說明可以檢視對應的詳細說明,只是說明這些命令是在這裡實現的。

以下是NameNode啟動部分的原始碼
主方法部分:

  public static void main(String argv[]) throws Exception {
    //檢查引數的合法性 在以NAMENODE啟動時不需要傳引數
    if (DFSUtil.parseHelpArgument(argv, NameNode.USAGE, System.out, true)) {
      System.exit(0);
    }

    try {
      StringUtils.startupShutdownMessage(NameNode.class, argv, LOG);
      //根據引數啟動對應的NameNode
      NameNode namenode = createNameNode(argv, null);
      if (namenode != null) {
        namenode.join();
      }
    } catch (Throwable e) {
      LOG.fatal("Failed to start namenode.", e);
      terminate(1, e);
    }
  }

createNameNode方法部分

  public static NameNode createNameNode(String argv[], Configuration conf)
      throws IOException {
    LOG.info("createNameNode " + Arrays.asList(argv));
    if (conf == null)
      conf = new HdfsConfiguration();
    //解析引數
    StartupOption startOpt = parseArguments(argv);
    if (startOpt == null) {
      printUsage(System.err);
      return null;
    }
    //將啟動引數加入到配置中
    setStartupOption(conf, startOpt);
    //根據引數不同啟動(或執行不同的方法)例項
    switch (startOpt) {
    //格式化HDFS檔案系統,格式化完成後退出
      case FORMAT: {
        boolean aborted = format(conf, startOpt.getForceFormat(),
            startOpt.getInteractiveFormat());
        terminate(aborted ? 1 : 0);
        return null; // avoid javac warning
      }
      //生成一個叢集ID對叢集無影響
      case GENCLUSTERID: {
        System.err.println("Generating new cluster id:");
        System.out.println(NNStorage.newClusterID());
        terminate(0);
        return null;
      }
      //這個命令不再被支援
      case FINALIZE: {
        System.err.println("Use of the argument '" + StartupOption.FINALIZE +
            "' is no longer supported. To finalize an upgrade, start the NN " +
            " and then run `hdfs dfsadmin -finalizeUpgrade'");
        terminate(1);
        return null; // avoid javac warning
      }
      //回滾
      case ROLLBACK: {
        boolean aborted = doRollback(conf, true);
        terminate(aborted ? 1 : 0);
        return null; // avoid warning
      }
      //同步active的映象,完成後退出
      case BOOTSTRAPSTANDBY: {
        String toolArgs[] = Arrays.copyOfRange(argv, 1, argv.length);
        int rc = BootstrapStandby.run(toolArgs, conf);
        terminate(rc);
        return null; // avoid warning
      }
      //初始化共享的edits 完成後退出
      case INITIALIZESHAREDEDITS: {
        boolean aborted = initializeSharedEdits(conf,
            startOpt.getForceFormat(),
            startOpt.getInteractiveFormat());
        terminate(aborted ? 1 : 0);
        return null; // avoid warning
      }
      //以BACKUP或者 CHECKPOINT的方式啟動
      //這裡的BackUpNode是NameNode的子類
      case BACKUP:
      case CHECKPOINT: {
        NamenodeRole role = startOpt.toNodeRole();
        DefaultMetricsSystem.initialize(role.toString().replace(" ", ""));
        return new BackupNode(conf, role);
      }
      //恢復
      case RECOVER: {
        NameNode.doRecovery(startOpt, conf);
        return null;
      }
      //檢查配置的正確性
      case METADATAVERSION: {
        printMetadataVersion(conf);
        terminate(0);
        return null; // avoid javac warning
      }
      //以升級的方式啟動
      case UPGRADEONLY: {
        DefaultMetricsSystem.initialize("NameNode");
        new NameNode(conf);
        terminate(0);
        return null;
      }
      //正常啟動NameNode
      default: {
        DefaultMetricsSystem.initialize("NameNode");
        return new NameNode(conf);
      }
    }
  }

OK由於篇幅問題這一篇就到這裡吧!

下一篇預報

下一篇將介紹NameNode正常啟動的過程,關於NameNode的其它命令部分的程式碼將在後面的
文章中專門的介紹。

說明文章的主線將以NameNode的啟動,和DataNode的通訊,以及Block的管理和DataNode的
管理展開,當主線瞭解完後再回頭展開介紹一些細節的程式碼。

以上內容部分參考了網路上的內容,歡迎大家指正討論
-聯絡方式:[email protected]

-每天進步一點點
-每天快樂一點點
-每天幸福一點點

相關推薦

一起Hadoop原始碼——HDFS01

寫在前面的話 這裡是跟我一起讀Hadoop原始碼系列的第一篇,主要記錄作者在讀Hadoop原始碼的過程 軟體版本 -Hadoop2.6.0 讀前知識 -瞭解RPC程式設計 -瞭解Java基礎 從NameNode開始 在Hadoop

一起學Mysql安裝和使用

DMBS分為兩類 基於共享檔案系統的DBMS 如 Access 基於C/S架構的DMBS 如 Mysql、Oracle、SqlServer 他們需要安裝客戶端和服務端 Mysql的版本 社群版(免費)相對於我們只要安裝社群版本就好 企業版(收

一起學windows初高階除錯1 --你為什麼要學除錯

                   跟我一起學windows初高階除錯之你為什麼要學除錯       本系列文章使用C/C++語言,vs自帶偵錯程式和windbg等其他相關除錯工具,介紹windows

Android 動畫原始碼學習

概述 Android提供了各種功能強大的應用動畫的使用者介面元素和繪製自定義的二維和三維圖形的應用。我們可以大致按照下面分類來學習理解 Animation 安卓框架提供了兩個動畫系統:屬性動畫和檢視動畫。屬性動畫在一般情況下,是首選的方法來使用,因為它更

logback原始碼系列文章——記錄日誌

今天晚上本來想來寫一下Logger怎麼記錄日誌,以及Appender元件。不過9點才從丈母孃家回來,又被幾個兄弟喊去喝酒,結果回來晚了,所以時間就只夠寫一篇Logger類的原始碼分析了。Appender找時間再寫 上篇部落格介紹了LoggerContext怎麼生成Logger

logback原始碼系列文章——記錄日誌的實際工作類Encoder

本系列的部落格從logback怎麼對接slf4j開始,逐步介紹了LoggerContext、Logger、ContextInitializer、Appender、Action等核心元件。跟讀logback的原始碼到這個程度,雖然不能說精通,不過至少日常的配置,和簡單的自定義擴

菜鳥江濤帶你學最小物聯網系統之模組01—— WIFI模組ESP12F初次親密接觸

最近想搞下物聯網相關的東西,淘寶上買了兩塊ESP12F的WiFi模組,於是大張旗鼓(偷偷摸摸)的搞起來,自己每天的學習進度在部落格上做個記錄,也給有類似想法的同學一個踩坑避雷的借鑑,大家共同進步,好了,閒話不多說,開始進入正題。 1.WIFI模組ESP12F的初次親密接觸。

python基礎01

python的基礎篇(01) 版本選擇 python2.7是python2的最後一個版本,到2020年將不再維護 python3.6是python3最新的版本中較穩定,是python方向的未來 py2與py3不相容,現在我們選擇python3進行講解,以後會對比p

一起學docker(18)--持續集成初級終結

any 啟動 任務 -a https 開發 封裝 p s load 如何持續集成imageimage0 :開發人員提交代碼到github1 :觸發jenkins操作2 :jenkins將代碼編譯、驗證3 :將代碼封裝在docker鏡像並上傳至docker倉庫4 :jenki

一起學Mysql基礎

資料庫常用的術語 DB:資料庫(databases)儲存資料的“倉庫”。它儲存了一系列有組織的資料 DBMS:資料庫管理系統(Database Management System)。資料庫是通過DBMS

「初級一起學docker(14)--docker swarm的使用

>>原創文章,歡迎轉載。轉載請註明:轉載自IT人故事會,謝謝! 1.什麼是Docker Swarm? 容器叢集管理工具。 通過docker swarm可以將多臺機器連線在一起,通過swarm的排程可以服務的多臺機器的部署,服務的伸縮。 docker-s

一起學python,網路程式設計基礎

Socket socket通常也稱作”套接字”,用於描述IP地址和埠,是一個通訊鏈的控制代碼,應用程式通常通過”套接字”向網路發出請求或者應答網路請求。 socket起源於Unix,而Unix/Linux基本哲學之一就是“一切皆檔案”,對於檔案用【開啟】【讀

一起學.NetCore之MVC過濾器,這看完走路可以仰著頭走

**前言** MVC過濾器在之前Asp.Net的時候就已經廣泛使用啦,不管是面試還是工作,總有一個考點或是需求涉及到,可以毫不疑問的說,這個技術點是非常重要的; 在之前參與的面試中,得知很多小夥伴只知道有一兩個過濾器,而對其執行順序瞭解的還是很模糊,少部分小夥伴甚至還沒有使用過。這裡就詳細來說說這塊的內容。

一起寫Makefile(七)

awk 註意事項 ack ref 個人 c語言 分開 數據庫 特性 make 的運行——————一般來說,最簡單的就是直接在命令行下輸入make命令,make命令會找當前目錄的makefile來執行,一切都是自動的。但也有時你也許只想讓make重編譯某些文件,而不是整個工程

一起寫Makefile(四)

比較 命令解釋 例子 exec 上層 tab鍵 file 順序 變量傳遞 書寫命令————每條規則中的命令和操作系統Shell的命令行是一致的。make會一按順序一條一條的執行命令,每條命令的開頭必須以[Tab]鍵開頭,除非,命令是緊跟在依賴規則後面的分號後的。在命令行之間

一起寫Makefile(三)

image 函數名 headers 波浪 用法 日期 最好 頭文件 哪些 書寫規則————規則包含兩個部分,一個是依賴關系,一個是生成目標的方法。在Makefile中,規則的順序是很重要的,因為,Makefile中只應該有一個最終目標,其它的目標都是被這個目標所連帶出來的,

一起學習VIM - vim插件合集

意思 同事 ipp 什麽是 如虎添翼 apple oca 終究 情況 2016-06-14 15:04 13333人閱讀 評論(0) 收藏 舉報 分類: Linux(104) 目錄(?)[+] 前兩天同事讓我在小組內部分享一下VIM,於是我花了一點時間寫了個簡短的教程。

一步一步學習hadoop(5)----hadoop Map/Reduce教程2

submit calc run submitjob des conf sam ner 打開 Map/Reduce用戶界面 本節為用戶採用框架要面對的各個環節提供了具體的描寫敘述,旨在與幫助用戶對實現、配置和調優進行具體的設置。然而,開發時候還是要相應著API進行

一起學python-01

跟我一起學python-01說明:1、python安裝選擇windows安裝,版本3.5.2 2.x版本和3.x版本區別比較大,老版本不支持新特性下載地址:https://www.python.org/downloads/windows/下載完成後解壓即可運行直接輸出內容:print("Hello W

一起學Unity3D】代碼中分割圖片而且載入幀序列動畫

stream textfield 控制 調整 我們 pos apply fonts 一個 在Cocos2dx中。對大圖的處理已經封裝好了一套自己的API,可是在Unity3D中貌似沒有類似的API(好吧,實際上是有的,並且功能更強大),或