Hadoop2.x集羣動態添加刪除數據節點

如果Hadoop集羣已經在運行了,這時可能需要動態的添加新的數據節點到Hadoop系統中去,或者將某個數據節點下線,由於業務的需要,集羣是不能重啓的,那麼具體的DataNode添加、刪除步驟是什麼樣的呢?

下面以DataNode的上線爲例詳細說明下如何動態的給HDFS集羣新增數據節點(Hadoop2.0版本)。

    首先簡單說下幾個相關的配置文件。

(1)由dfs.hosts配置選項指定的白名單文件,當要新上線數據節點的時候,需要把數據節點的名字追加在此文件中;

(2)由dfs.hosts.exclude配置選項指定的黑名單文件,當要下線數據節點的時候,需要把數據節點的名字追加在此文件中;

    下面開始步驟(假設所有新增數據節點上的Hadoop環境都已經部署完畢):

Step1:關閉新加入數據節點的防火牆。

Step2:在兩個NameNode節點的hosts文件中加入新增數據節點的hostname。

Step3:在每個新增數據節點的hosts文件中加入兩個NameNode的hostname。

Step4:在兩個NameNode上,打通向新增數據節點無密鑰SSH登錄的通道。

Step5:在兩個NameNode上的dfs.hosts指定的白名單文件中追加上所有新增的數據節點的hostname,注意是追加!並且,保證在dfs.hosts.exclude指定的黑名單文件中不含有新增的數據節點的hostname。

Step6:找一個客戶端,配置文件和其他節點一致,執行如下刷新命令:

  hdfs dfsadmin -refreshNodes

      (此步也可以在任何其他節點上進行)

Step7:還是在第6步的客戶端上操作,此時需要更改下hdfs-site.xml中的配置選項,將類似於如下的配置選項:

複製代碼
<property>
         <name>dfs.namenode.rpc-address.mcs.nn0</name>
         <value>namenode0:9000</value>
</property>
<property>
      <name>dfs.namenode.rpc-address.mcs.nn1</name>
      <value>namenode1:9000</value>
</property>
複製代碼

改爲:

複製代碼
<property>
    <name>dfs.namenode.rpc-address.mcs.nn0</name>
    <value>namenode1:9000</value>
</property>
<property>
    <name>dfs.namenode.rpc-address.mcs.nn1</name>
    <value>namendoe0:9000</value>
</property>
複製代碼

Step8:在第7步操作的客戶端上重新執行命令:

  hdfs dfsadmin -refreshNodes

Step9:在數據節點上啓動DataNode進程,命令如下:

  hadoop-daemon.sh start datanode

Step10:查看數據節點進程的情況(通過日誌),查看NameNode的web界面。

Step11:在兩個NameNode節點上,更改slaves文件,將要上線的數據節點hostname追加到slaves文件中。

至於第7步中爲什麼要更改配置之後在進行第8步的刷新,是因爲在Hadoop2.x版本中引入了Federation機制,用戶可根據情況定義多組NameNode,每一組有兩個NameNode,一個爲active,另一個爲standby,實現了HA。由於執行刷新命令的節點相當於一個Client,Client將觸發當前nameservice中的第一個NameNode執行刷新命令,要使得兩個NameNode都刷新,則要更改下配置之後再刷新。具體來說刷新是調用如下方法:

複製代碼
public int refreshNodes() throws IOException {

    int exitCode = -1; 

    DistributedFileSystem dfs = getDFS();

    dfs.refreshNodes();

    exitCode = 0;

    return exitCode;

  }
複製代碼

    通過獲取文件系統對象FileSystem之後,調用FSNamesystem類中的refreshNodes方法:

複製代碼
void refreshNodes() throws IOException {

    checkOperation(OperationCategory.UNCHECKED);

    checkSuperuserPrivilege();

    getBlockManager().getDatanodeManager().refreshNodes(new HdfsConfiguration());

  }
複製代碼

    在檢查完相應的操作權限之後,最後由DatanodeManager類來執行具體的刷新實現:

複製代碼
public void refreshNodes(final Configuration conf) throws IOException {

    refreshHostsReader(conf);

    namesystem.writeLock();

    try {

      refreshDatanodes();

    } finally {

      namesystem.writeUnlock();

    }

  }
複製代碼

    其中,refreshHostsReader是重新讀取dfs.hosts指定的配置文件,將其中的內容加載到內存中,更新白名單列表includes。之後,執行最關鍵的一步,刷新數據節點列表:

複製代碼
private void refreshDatanodes() throws IOException {

    for(DatanodeDescriptor node : datanodeMap.values()) {

      // Check if not include.

      if (!inHostsList(node)) {

        node.setDisallowed(true); // case 2.

      } else {

        if (inExcludedHostsList(node)) {

          startDecommission(node); // case 3.

        } else {

          stopDecommission(node); // case 4.

        }

      }

    }

  }
複製代碼

    此處的inHostsList方法是當數據節點發來心跳進行註冊的時候,判斷此節點是否在白名單之中,如果不在的話,就會拒絕該數據節點的註冊請求,並拋出異常:

DisallowedDatanodeException:"Datanode denied communication with namenode: " + nodeID

    至於數據節點的下線,和上述步驟類似,只不過Step5中要換一下文件。整個操作的過程中都不涉及集羣的重啓~

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章