【hadoop】12.HDFS-NameNode工做機制

簡介

經過本教程您能夠學習到:node

  1. NameNode&Secondary NameNode工做機制;
  2. 鏡像文件和編輯日誌文件是什麼;
  3. 滾動編輯日誌是什麼;
  4. namenode版本號;
  5. SecondaryNameNode目錄結構;
  6. namenode安全模式;

一、NameNode & Secondary NameNode工做機制

NN以及2NN的工做機制以下圖所示web

NN和SNN的工做原理

其中chkpoint檢查時間參數設置shell

  • 一般狀況下,SecondaryNameNode每隔一小時執行一次。
[hdfs-default.xml]
<property>
  <name>dfs.namenode.checkpoint.period</name>
  <value>3600</value>
</property>
  • 一分鐘檢查一次操做次數,當操做次數達到1百萬時,SecondaryNameNode執行一次。

一、namenode工做json

  • 第一次啓動namenode格式化後,建立fsimage和edits文件。若是不是第一次啓動,直接加載編輯日誌和鏡像文件到內存。
  • 客戶端對元數據進行增刪改的請求
  • namenode記錄操做日誌,更新滾動日誌。
  • namenode在內存中對數據進行增刪改查

二、Secondary NameNode工做安全

  • Secondary NameNode詢問namenode是否須要checkpoint。直接帶回namenode是否檢查結果。
  • Secondary NameNode請求執行checkpoint。
  • namenode滾動正在寫的edits日誌
  • 將滾動前的編輯日誌和鏡像文件拷貝到Secondary NameNode
  • Secondary NameNode加載編輯日誌和鏡像文件到內存,併合並。
  • 生成新的鏡像文件fsimage.chkpoint
  • 拷貝fsimage.chkpoint到namenode
  • namenode將fsimage.chkpoint從新命名成fsimage

二、NameNode中的重要文件

前面咱們提到NN處理過程當中的兩類關鍵文件,一個是編輯日誌,另外一個則是鏡像文件,咱們來看看他們究竟是什麼。bash

位於/opt/module/hadoop-2.7.2/data/tmp/dfs/name/current目錄中產生的文件。他們產生於namenode被格式化以後,將產生以下文件數據結構

edits_0000000000000000000
fsimage_0000000000000000000.md5
seen_txid
VERSION

其中:oop

  • seen_txid文件保存的是一個數字,就是最後一個edits_的數字
  • Fsimage文件:HDFS文件系統元數據的一個永久性的檢查點,其中包含HDFS文件系統的全部目錄和文件idnode的序列化信息。 
  • Edits文件:存放HDFS文件系統的全部更新操做的路徑,文件系統客戶端執行的全部寫操做首先會被記錄到edits文件中。 
  • 每次Namenode啓動的時候都會將fsimage文件讀入內存,並從00001開始到seen_txid中記錄的數字依次執行每一個edits裏面的更新操做,保證內存中的元數據信息是最新的、同步的,能夠當作Namenode啓動的時候就將fsimage和edits文件進行了合併。
[root@h133 current]# pwd
/opt/module/hadoop-2.7.2/data/tmp/dfs/name/current
[root@h133 current]# ll
總用量 3204
...
-rw-r--r--. 1 root root      42 1月   4 10:47 edits_0000000000000000086-0000000000000000087
-rw-r--r--. 1 root root      42 1月   4 11:42 edits_0000000000000000088-0000000000000000089
-rw-r--r--. 1 root root      42 1月   4 12:37 edits_0000000000000000090-0000000000000000091
-rw-r--r--. 1 root root    3406 1月   4 13:32 edits_0000000000000000092-0000000000000000134
-rw-r--r--. 1 root root      42 1月   4 14:28 edits_0000000000000000135-0000000000000000136
-rw-r--r--. 1 root root 1048576 1月   4 14:28 edits_inprogress_0000000000000000137
-rw-r--r--. 1 root root    1027 1月   4 13:33 fsimage_0000000000000000134
-rw-r--r--. 1 root root      62 1月   4 13:33 fsimage_0000000000000000134.md5
-rw-r--r--. 1 root root    1027 1月   4 14:28 fsimage_0000000000000000136
-rw-r--r--. 1 root root      62 1月   4 14:28 fsimage_0000000000000000136.md5
-rw-r--r--. 1 root root       4 1月   4 14:28 seen_txid
-rw-r--r--. 1 root root     208 1月   3 15:10 VERSION

2.一、seen_txid文件

seen_txid的內容比較簡單,單純的一個數字,表明最後一個edits_的序號,咱們能夠直接經過cat命令進行查看:佈局

[root@h133 current]# cat seen_txid 
137

137,恰好對應的edits_inprogress當前的下標。學習

2.二、鏡像文件

鏡像文件,即fsimage文件,前面提到,他的內容已是序列化字節碼,所以咱們直接查看的話,會出現亂碼。官方提供了命令方便咱們查看內容:

hdfs oiv -p 解碼進程 -i 輸入——鏡像文件 -o 輸出——轉換後文件輸出路徑

解碼進程通常使用XML,或者使用默認的Ls。

接下來咱們使用XML解碼進程將文件轉化爲一個xml文件,而後在本身的機器上使用比較好的編譯器查看XML內容

hdfs oiv -p XML -i fsimage_0000000000000000136 -o myfsimage.xml

我甚至覺得支持json格式,嘗試了一下不行,但願之後的版本支持輸出json格式。json & yml,這兩個一個是數據傳輸、一個是文件配置的最佳選擇。

查看文件內容以下:

<?xml version="1.0"?>
<fsimage>
    <NameSection>
        <genstampV1>1000</genstampV1>
        <genstampV2>1014</genstampV2>
        <genstampV1Limit>0</genstampV1Limit>
        <lastAllocatedBlockId>1073741838</lastAllocatedBlockId>
        <txid>136</txid>
    </NameSection>
    <INodeSection>
        <lastInodeId>16403</lastInodeId>
        <inode>
            <id>16385</id>
            <type>DIRECTORY</type>
            <name></name>
            <mtime>1546499650677</mtime>
            <permission>root:supergroup:rwxr-xr-x</permission>
            <nsquota>9223372036854775807</nsquota>
            <dsquota>-1</dsquota>
        </inode>
        <inode>
            <id>16386</id>
            <type>DIRECTORY</type>
            <name>user</name>
            <mtime>1546579469553</mtime>
            <permission>root:supergroup:rwxr-xr-x</permission>
            <nsquota>-1</nsquota>
            <dsquota>-1</dsquota>
        </inode>
        <inode>
            <id>16387</id>
            <type>DIRECTORY</type>
            <name>zhaoyi</name>
            <mtime>1546502296962</mtime>
            <permission>root:supergroup:rwxr-xr-x</permission>
            <nsquota>-1</nsquota>
            <dsquota>-1</dsquota>
        </inode>
        ....

不難看出,該文件記錄了咱們HDFS文件目錄結構以及一些inode信息。

2.三、編輯日誌

接下來咱們轉化編輯日誌文件(edits_xxxx)爲XML格式。他使用另外一個命令操做:

hdfs oev -p 文件類型 -i 編輯日誌 -o 轉換後文件輸出路徑

在執行此操做以前,咱們就直接轉換,發現最新的edits文件中並無任何數據,說明已經進行過一次合併(參見圖示)。接下來咱們上傳一個文件,而後在進行轉換

dfs oev -p XML -i edits_inprogress_0000000000000000139 -o edits.xml

獲得以下的XML文件內容:

<?xml version="1.0" encoding="UTF-8"?>
<EDITS>
  <EDITS_VERSION>-63</EDITS_VERSION>
  <RECORD>
    <OPCODE>OP_START_LOG_SEGMENT</OPCODE>
    <DATA>
      <TXID>139</TXID>
    </DATA>
  </RECORD>
  <RECORD>
    <OPCODE>OP_ADD</OPCODE>
    <DATA>
      <TXID>140</TXID>
      <LENGTH>0</LENGTH>
      <INODEID>16404</INODEID>
      <PATH>/seen_txid._COPYING_</PATH>
      <REPLICATION>3</REPLICATION>
      <MTIME>1546588237534</MTIME>
      <ATIME>1546588237534</ATIME>
      <BLOCKSIZE>134217728</BLOCKSIZE>
      <CLIENT_NAME>DFSClient_NONMAPREDUCE_302138823_1</CLIENT_NAME>
      <CLIENT_MACHINE>192.168.102.133</CLIENT_MACHINE>
      <OVERWRITE>true</OVERWRITE>
      <PERMISSION_STATUS>
        <USERNAME>root</USERNAME>
        <GROUPNAME>supergroup</GROUPNAME>
        <MODE>420</MODE>
      </PERMISSION_STATUS>
      <RPC_CLIENTID>d56baf74-71a1-4e2e-a64c-9b6ba88d5552</RPC_CLIENTID>
      <RPC_CALLID>3</RPC_CALLID>
    </DATA>
  </RECORD>
  <RECORD>
    <OPCODE>OP_ALLOCATE_BLOCK_ID</OPCODE>
    <DATA>
      <TXID>141</TXID>
      <BLOCK_ID>1073741839</BLOCK_ID>
    </DATA>
  </RECORD>
  <RECORD>
    <OPCODE>OP_SET_GENSTAMP_V2</OPCODE>
    <DATA>
      <TXID>142</TXID>
      <GENSTAMPV2>1015</GENSTAMPV2>
    </DATA>
  </RECORD>
  <RECORD>
    <OPCODE>OP_ADD_BLOCK</OPCODE>
    <DATA>
      <TXID>143</TXID>
      <PATH>/seen_txid._COPYING_</PATH>
      <BLOCK>
        <BLOCK_ID>1073741839</BLOCK_ID>
        <NUM_BYTES>0</NUM_BYTES>
        <GENSTAMP>1015</GENSTAMP>
      </BLOCK>
      <RPC_CLIENTID></RPC_CLIENTID>
      <RPC_CALLID>-2</RPC_CALLID>
    </DATA>
  </RECORD>
  <RECORD>
    <OPCODE>OP_CLOSE</OPCODE>
    <DATA>
      <TXID>144</TXID>
      <LENGTH>0</LENGTH>
      <INODEID>0</INODEID>
      <PATH>/seen_txid._COPYING_</PATH>
      <REPLICATION>3</REPLICATION>
      <MTIME>1546588238055</MTIME>
      <ATIME>1546588237534</ATIME>
      <BLOCKSIZE>134217728</BLOCKSIZE>
      <CLIENT_NAME></CLIENT_NAME>
      <CLIENT_MACHINE></CLIENT_MACHINE>
      <OVERWRITE>false</OVERWRITE>
      <BLOCK>
        <BLOCK_ID>1073741839</BLOCK_ID>
        <NUM_BYTES>4</NUM_BYTES>
        <GENSTAMP>1015</GENSTAMP>
      </BLOCK>
      <PERMISSION_STATUS>
        <USERNAME>root</USERNAME>
        <GROUPNAME>supergroup</GROUPNAME>
        <MODE>420</MODE>
      </PERMISSION_STATUS>
    </DATA>
  </RECORD>
  <RECORD>
    <OPCODE>OP_RENAME_OLD</OPCODE>
    <DATA>
      <TXID>145</TXID>
      <LENGTH>0</LENGTH>
      <SRC>/seen_txid._COPYING_</SRC>
      <DST>/seen_txid</DST>
      <TIMESTAMP>1546588238066</TIMESTAMP>
      <RPC_CLIENTID>d56baf74-71a1-4e2e-a64c-9b6ba88d5552</RPC_CLIENTID>
      <RPC_CALLID>8</RPC_CALLID>
    </DATA>
  </RECORD>
</EDITS>

從中能夠了解到咱們往根路徑下上傳了一個seen.txid文件以後的編輯日誌的記錄信息。不少狀況下,該文件可能會具備不少的歷史數據。這對於咱們想單獨調試某個操做的時候,沒法定位準備的日誌,這就須要咱們「清空」最新的edits文件的歷史數據。

這就須要咱們滾動當前的日誌了。

如何滾動?調用命令

hdfs dfsadmin -rollEdtis

例如:

[root@h133 current]# hdfs dfsadmin -rollEdits
Successfully rolled edit logs.
New segment starts at txid 147

能夠看到,新的分片id變成了147,咱們也能夠查看當前最新的分片日誌文件爲edits_inprogress_0000000000000000147:

[root@h133 current]# ll edits*
-rw-r--r--. 1 root root      42 1月   3 15:12 edits_0000000000000000001-0000000000000000002
....
-rw-r--r--. 1 root root      42 1月   4 15:23 edits_0000000000000000137-0000000000000000138
-rw-r--r--. 1 root root     527 1月   4 15:59 edits_0000000000000000139-0000000000000000146
-rw-r--r--. 1 root root 1048576 1月   4 15:59 edits_inprogress_0000000000000000147

轉化XML的日誌進行查看,文件內容就比較乾淨了,方便咱們進行一些調試:

[root@h133 current]# hdfs oev -p XML -i edits_inprogress_0000000000000000147 -o edits.xml 
[root@h133 current]# cat edits.xml 
<?xml version="1.0" encoding="UTF-8"?>
<EDITS>
  <EDITS_VERSION>-63</EDITS_VERSION>
  <RECORD>
    <OPCODE>OP_START_LOG_SEGMENT</OPCODE>
    <DATA>
      <TXID>147</TXID>
    </DATA>
  </RECORD>
</EDITS>

2.四、版本文件VERSION

該文件namenode中一些版本號的信息。

root@h133 current]# cat VERSION 
#Thu Jan 03 15:10:44 CST 2019
namespaceID=1140718114
clusterID=CID-5b84c9ed-504a-4885-9e26-b9e99eefaf21
cTime=0
storageType=NAME_NODE
blockpoolID=BP-2054658932-192.168.102.133-1546499444184
layoutVersion=-63
  • namespaceID在HDFS上,會有多個Namenode,因此不一樣Namenode的namespaceID是不一樣的,分別管理一組blockpoolID。
  • clusterID集羣id,全局惟一
  • cTime屬性標記了namenode存儲系統的建立時間,對於剛剛格式化的存儲系統,這個屬性爲0;可是在文件系統升級以後,該值會更新到新的時間戳。
  • storageType屬性說明該存儲目錄包含的是namenode的數據結構。
  • blockpoolID:一個block pool id標識一個block pool,而且是跨集羣的全局惟一。當一個新的Namespace被建立的時候(format過程的一部分)會建立並持久化一個惟一ID。在建立過程構建全局惟一的BlockPoolID比人爲的配置更可靠一些。NN將BlockPoolID持久化到磁盤中,在後續的啓動過程當中,會再次load並使用。
  • layoutVersion是一個負整數。一般只有HDFS增長新特性時纔會更新這個版本號。

其中,最主要的就是namespaceID,他是當前NN的惟一標識;

另一個則是clusterID,咱們查看其它節點的該文件能夠發現,你們同屬一個集羣,那麼clusterID則都相等;

再有,就是storageType字段,不一樣類型的節點對應的不一樣,例如當前這個文件是NN的,則其值就爲namenode。查看其它節點的不一樣類型storageType值,DN的則爲DATA_NODE,而2NN的則和NN同樣,都爲NAME_NODE(畢竟幫NN作namenode最苦的活,是該獲得相同的名分。)

三、SecondaryNameNode目錄結構

Secondary NameNode用來監控HDFS狀態的輔助後臺程序,每隔一段時間獲取HDFS元數據的快照。

在/opt/module/hadoop-2.7.2/data/tmp/dfs/namesecondary/current這個目錄中查看SecondaryNameNode目錄結構。

[root@h135 current]# pwd
/opt/module/hadoop-2.7.2/data/tmp/dfs/namesecondary/current
[root@h135 current]# ll
總用量 2280
-rw-r--r--. 1 root root      42 1月   3 23:58 edits_0000000000000000001-0000000000000000002
...
-rw-r--r--. 1 root root      42 1月   6 01:16 edits_0000000000000000191-0000000000000000192
-rw-r--r--. 1 root root      42 1月   6 02:16 edits_0000000000000000193-0000000000000000194
-rw-r--r--. 1 root root    1095 1月   6 01:16 fsimage_0000000000000000192
-rw-r--r--. 1 root root      62 1月   6 01:16 fsimage_0000000000000000192.md5
-rw-r--r--. 1 root root    1095 1月   6 02:16 fsimage_0000000000000000194
-rw-r--r--. 1 root root      62 1月   6 02:16 fsimage_0000000000000000194.md5
-rw-r--r--. 1 root root     208 1月   6 02:16 VERSION

顯然,SecondaryNameNode的namesecondary/current目錄和主namenode的current目錄的佈局相同。這樣的好處在於:當主namenode發生故障時(假設沒有及時備份數據),能夠從SecondaryNameNode恢復數據。

  • 方法一:將SecondaryNameNode中數據拷貝到namenode存儲數據的目錄;
  • 方法二:使用-importCheckpoint選項啓動namenode守護進程,從而將SecondaryNameNode用做新的主namenode。

3.一、拷貝恢復

咱們來實操一下方法一的結果。

一、在h133(NN)上殺死namenode守護進程,同時刪除掉name目錄,模擬比較完全的集羣故障。

[root@h133 dfs]# kill -9 10392
[root@h133 dfs]# jps
14550 Jps
10520 DataNode
10684 NodeManager
[root@h133 dfs]# pwd
/opt/module/hadoop-2.7.2/data/tmp/dfs
[root@h133 dfs]# rm -rf name/*

這時候咱們沒法訪問web,也沒法執行任何業務操做(上傳、文件)了。

二、接下來來到h135(2NN)上,執行拷貝操做:

[root@h135 dfs]# scp -r namesecondary/* root@h133:/opt/module/hadoop-2.7.2/data/tmp/dfs/name

三、在h133上單獨啓動namenode守護進程

root@h133 dfs]# hadoop-daemon.sh start namenode

等待namenode恢復狀態,一切恢復如初。

3.二、2NN替換NN修復

模擬namenode故障,並採用方法二,恢復namenode數據

(1)修改hdfs-site.xml中的

<!-- 配置檢查點的檢查頻率 -->
<property>
  <name>dfs.namenode.checkpoint.period</name>
  <value>120</value>
</property>

<!-- 配置namenode的文件目錄 -->
<property>
  <name>dfs.namenode.name.dir</name>
  <value>/opt/module/hadoop-2.7.2/data/tmp/dfs/name</value>
</property>

(2)kill -9 namenode進程

kill -9  xxxxx

(3)刪除namenode存儲的數據(/opt/module/hadoop-2.7.2/data/tmp/dfs/name)

rm -rf /opt/module/hadoop-2.7.2/data/tmp/dfs/name/*

(4)若是SecondaryNameNode不和Namenode在一個主機節點上,須要將SecondaryNameNode存儲數據的目錄拷貝到Namenode存儲數據的平級目錄。

pwd
/opt/module/hadoop-2.7.2/data/tmp/dfs
ls
data  name  namesecondary

(5)導入檢查點數據(等待一會ctrl+c結束掉)

bin/hdfs namenode -importCheckpoint

(6)啓動namenode

sbin/hadoop-daemon.sh start namenode

(7)若是提示文件鎖了,能夠刪除in_use.lock

rm -rf /opt/module/hadoop-2.7.2/data/tmp/dfs/namesecondary/in_use.lock

四、安全模式

Namenode啓動時,首先將映像文件(fsimage)載入內存,並執行編輯日誌(edits)中的各項操做。一旦在內存中成功創建文件系統元數據的映像,則建立一個新的fsimage文件和一個空的編輯日誌。此時,namenode開始監聽datanode請求。爲了避免受到外部請求的干擾,namenode會運行在安全模式下,最直接的表現爲:文件系統對於客戶端來講是隻讀的。

系統中的數據塊的位置並非由namenode維護的,而是以塊列表的形式存儲在datanode中。在系統的正常操做期間,namenode會在內存中保留全部塊位置的映射信息。在安全模式下,各個datanode會向namenode發送最新的塊列表信息,namenode瞭解到足夠多的塊位置信息以後,便可高效運行文件系統。

若是知足「最小副本條件」,namenode會在30秒鐘以後就退出安全模式。在啓動一個剛剛格式化的HDFS集羣時,由於系統中尚未任何塊,因此namenode不會進入安全模式。可是若是是集羣重啓、故障恢復等從一個原有狀態開始啓動集羣狀態,則會啓動安全模式,相信前面在模擬namenode故障時,您也有遇到安全模式。

最小副本條件:整個文件系統中99.9%的塊知足最小副本級別(默認值:dfs.replication.min=1)。

集羣處於安全模式,不能執行重要操做(寫操做)。集羣啓動完成後,自動退出安全模式。關於安全模式的相關命令有:

(1)bin/hdfs dfsadmin -safemode get		(功能描述:查看安全模式狀態)
(2)bin/hdfs dfsadmin -safemode enter  	(功能描述:進入安全模式狀態)
(3)bin/hdfs dfsadmin -safemode leave	(功能描述:離開安全模式狀態)
(4)bin/hdfs dfsadmin -safemode wait	(功能描述:等待安全模式狀態)

一、查看安全模式狀態

[root@h134 ~]# hdfs dfsadmin -safemode get
Safe mode is OFF
[root@h134 ~]# hadoop fs -put h134.txt 
put: `.': No such file or directory
[root@h134 ~]# hadoop fs -put h134.txt /
[root@h134 ~]# hadoop fs -cat /h134.txt
this is h134 file.

當前狀態爲OFF,咱們能夠正常的文件上傳操做。

二、進入安全模式

[root@h134 ~]# hdfs dfsadmin -safemode enter
Safe mode is ON
[root@h134 ~]# hdfs dfsadmin -safemode get
Safe mode is ON
[root@h134 ~]# hadoop fs -put h134.txt /
put: `/h134.txt': File exists
[root@h134 ~]# hadoop fs -cat /h134.txt
this is h134 file.

能夠看到,進入安全模式以後,HDFS文件系統不支持咱們的寫入操做,但支持讀取操做。

三、離開安全模式

[root@h134 ~]# hdfs dfsadmin -safemode leave
Safe mode is OFF

四、等待安全模式

這個模式,有點相似於消息隊列的原理。當咱們執行一個任務時,能夠等待隊列有了充分的準備以後才執行咱們的任務。這裏表現爲:指定一個任務,安全模式關閉以後當即執行。

如今咱們編寫一個shell腳本,簡單的定義個上傳文件的任務,在安全模式開啓的狀況下讓其等待。要完成該需求,就可使用等待安全模式的命令。

[root@h134 ~]# vi wait_safe.sh
#!/bin/bash
echo "waiting for safe mode off..."
hdfs dfsadmin -safemode wait
echo "safe mode off, start upload file..."
hadoop fs -put ~/h134.txt /user
echo "upload done..."

接下來咱們使用xshell從新創建一個會話,用2個窗口來演示這個過程。

(1)會話一先開啓集羣的安全模式:

[root@h134 ~]# clear
[root@h134 ~]# hdfs dfsadmin -safemode enter
Safe mode is ON

(2)會話二執行任務腳本:

[root@h134 ~]# sh wait_safe.sh 
waiting for safe mode off...

能夠看到,當前腳本阻塞在命令hdfs dfsadmin -safemode wait上,正是咱們想要的效果。

(3)會話一離開安全模式

[root@h134 ~]# hdfs dfsadmin -safemode leave
Safe mode is OFF

(4)立馬切換到會話二的窗口:

[root@h134 ~]# sh wait_safe.sh 
waiting for safe mode off...
Safe mode is OFF
safe mode off, start upload file...
upload done...

這樣,就能在安全模式關閉的第一時間完成咱們的上傳任務了。

相關文章
相關標籤/搜索