經過本教程您能夠學習到:node
NN以及2NN的工做機制以下圖所示web
其中chkpoint檢查時間參數設置shell
[hdfs-default.xml] <property> <name>dfs.namenode.checkpoint.period</name> <value>3600</value> </property>
一、namenode工做json
二、Secondary NameNode工做安全
前面咱們提到NN處理過程當中的兩類關鍵文件,一個是編輯日誌,另外一個則是鏡像文件,咱們來看看他們究竟是什麼。bash
位於/opt/module/hadoop-2.7.2/data/tmp/dfs/name/current目錄中產生的文件。他們產生於namenode被格式化以後,將產生以下文件數據結構
edits_0000000000000000000 fsimage_0000000000000000000.md5 seen_txid VERSION
其中:oop
[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
seen_txid的內容比較簡單,單純的一個數字,表明最後一個edits_的序號,咱們能夠直接經過cat命令進行查看:佈局
[root@h133 current]# cat seen_txid 137
137,恰好對應的edits_inprogress當前的下標。學習
鏡像文件,即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信息。
接下來咱們轉化編輯日誌文件(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>
該文件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,他是當前NN的惟一標識;
另一個則是clusterID,咱們查看其它節點的該文件能夠發現,你們同屬一個集羣,那麼clusterID則都相等;
再有,就是storageType字段,不一樣類型的節點對應的不一樣,例如當前這個文件是NN的,則其值就爲namenode。查看其它節點的不一樣類型storageType值,DN的則爲DATA_NODE,而2NN的則和NN同樣,都爲NAME_NODE(畢竟幫NN作namenode最苦的活,是該獲得相同的名分。)
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恢復數據。
咱們來實操一下方法一的結果。
一、在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恢復狀態,一切恢復如初。
模擬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...
這樣,就能在安全模式關閉的第一時間完成咱們的上傳任務了。