HDFS(Hadoop Distributed File System) 分佈式文件系統,HDFS是一個高度容錯性的系統,適合部署在廉價的機器上。HDFS能提供高吞吐量的數據訪問,很是適合大規模數據集上的應用.由NameNode,若干DataNode,以及Secondary NameNode組成。node
經常使用命令實操 (0)啓動Hadoop集羣(方便後續的測試) [atguigu@hadoop102 hadoop-2.7.2]$ sbin/start-dfs.sh [atguigu@hadoop103 hadoop-2.7.2]$ sbin/start-yarn.sh (1)-help:輸出這個命令參數 [atguigu@hadoop102 hadoop-2.7.2]$ hadoop fs -help rm (2)-ls: 顯示目錄信息 [atguigu@hadoop102 hadoop-2.7.2]$ hadoop fs -ls / (3)-mkdir:在HDFS上建立目錄 [atguigu@hadoop102 hadoop-2.7.2]$ hadoop fs -mkdir -p /sanguo/shuguo (4)-moveFromLocal:從本地剪切粘貼到HDFS [atguigu@hadoop102 hadoop-2.7.2]$ touch kongming.txt [atguigu@hadoop102 hadoop-2.7.2]$ hadoop fs -moveFromLocal ./kongming.txt /sanguo/shuguo (5)-appendToFile:追加一個文件到已經存在的文件末尾 [atguigu@hadoop102 hadoop-2.7.2]$ touch liubei.txt [atguigu@hadoop102 hadoop-2.7.2]$ vi liubei.txt 輸入 san gu mao lu [atguigu@hadoop102 hadoop-2.7.2]$ hadoop fs -appendToFile liubei.txt /sanguo/shuguo/kongming.txt (6)-cat:顯示文件內容 [atguigu@hadoop102 hadoop-2.7.2]$ hadoop fs -cat /sanguo/shuguo/kongming.txt (7)-chgrp 、-chmod、-chown:Linux文件系統中的用法同樣,修改文件所屬權限 [atguigu@hadoop102 hadoop-2.7.2]$ hadoop fs -chmod 666 /sanguo/shuguo/kongming.txt [atguigu@hadoop102 hadoop-2.7.2]$ hadoop fs -chown atguigu:atguigu /sanguo/shuguo/kongming.txt (8)-copyFromLocal:從本地文件系統中拷貝文件到HDFS路徑去 [atguigu@hadoop102 hadoop-2.7.2]$ hadoop fs -copyFromLocal README.txt / (9)-copyToLocal:從HDFS拷貝到本地 [atguigu@hadoop102 hadoop-2.7.2]$ hadoop fs -copyToLocal /sanguo/shuguo/kongming.txt ./ (10)-cp :從HDFS的一個路徑拷貝到HDFS的另外一個路徑 [atguigu@hadoop102 hadoop-2.7.2]$ hadoop fs -cp /sanguo/shuguo/kongming.txt /zhuge.txt (11)-mv:在HDFS目錄中移動文件 [atguigu@hadoop102 hadoop-2.7.2]$ hadoop fs -mv /zhuge.txt /sanguo/shuguo/ (12)-get:等同於copyToLocal,就是從HDFS下載文件到本地 [atguigu@hadoop102 hadoop-2.7.2]$ hadoop fs -get /sanguo/shuguo/kongming.txt ./ (13)-getmerge:合併下載多個文件,好比HDFS的目錄 /user/atguigu/test下有多個文件:log.1, log.2,log.3,... [atguigu@hadoop102 hadoop-2.7.2]$ hadoop fs -getmerge /user/atguigu/test/* ./zaiyiqi.txt (14)-put:等同於copyFromLocal [atguigu@hadoop102 hadoop-2.7.2]$ hadoop fs -put ./zaiyiqi.txt /user/atguigu/test/ (15)-tail:顯示一個文件的末尾 [atguigu@hadoop102 hadoop-2.7.2]$ hadoop fs -tail /sanguo/shuguo/kongming.txt (16)-rm:刪除文件或文件夾 [atguigu@hadoop102 hadoop-2.7.2]$ hadoop fs -rm /user/atguigu/test/jinlian2.txt (17)-rmdir:刪除空目錄 [atguigu@hadoop102 hadoop-2.7.2]$ hadoop fs -mkdir /test [atguigu@hadoop102 hadoop-2.7.2]$ hadoop fs -rmdir /test (18)-du統計文件夾的大小信息 [atguigu@hadoop102 hadoop-2.7.2]$ hadoop fs -du -s -h /user/atguigu/test 2.7 K /user/atguigu/test [atguigu@hadoop102 hadoop-2.7.2]$ hadoop fs -du -h /user/atguigu/test 1.3 K /user/atguigu/test/README.txt 15 /user/atguigu/test/jinlian.txt 1.4 K /user/atguigu/test/zaiyiqi.txt (19)-setrep:設置HDFS中文件的副本數量 [atguigu@hadoop102 hadoop-2.7.2]$ hadoop fs -setrep 10 /sanguo/shuguo/kongming.txt
圖3-3 HDFS副本數量 這裏設置的副本數只是記錄在NameNode的元數據中,是否真的會有這麼多副本,還得看DataNode的數量。由於目前只有3臺設備,最多也就3個副本,只有節點數的增長到10臺時,副本數才能達到10。
1)客戶端經過Distributed FileSystem模塊向NameNode請求上傳文件,NameNode檢查目標文件是否已存在,父目錄是否存在。apache
2)NameNode返回是否能夠上傳。bootstrap
3)客戶端請求第一個 Block上傳到哪幾個DataNode服務器上。promise
4)NameNode返回3個DataNode節點,分別爲dn一、dn二、dn3。瀏覽器
5)客戶端經過FSDataOutputStream模塊請求dn1上傳數據,dn1收到請求會繼續調用dn2,而後dn2調用dn3,將這個通訊管道創建完成。緩存
6)dn一、dn二、dn3逐級應答客戶端。安全
7)客戶端開始往dn1上傳第一個Block(先從磁盤讀取數據放到一個本地內存緩存),以Packet爲單位,dn1收到一個Packet就會傳給dn2,dn2傳給dn3;dn1每傳一個packet會放入一個應答隊列等待應答。服務器
8)當一個Block傳輸完成以後,客戶端再次請求NameNode上傳第二個Block的服務器。(重複執行3-7步)。網絡
在HDFS寫數據的過程當中,NameNode會選擇距離待上傳數據最近距離的DataNode接收數據。那麼這個最近距離怎麼計算呢?架構
節點距離:兩個節點到達最近的共同祖先的距離總和。
DN1是最近的,DN2和DN3是根據第一個節點DN1選出來的;
第二次的DN四、DN五、DN6可能跟第一次傳輸的DN同樣,也可能不同取決於內部集羣的情況;兩次返回的DN都是獨立的。
N1與N2之間的距離爲2;(找線條數)
假設N一、N二、N3三臺機器,從N1上傳數據,則最短的節點就是它自己0;
後兩個的選擇是根據機架感知來選:
1)客戶端經過Distributed FileSystem向NameNode請求下載文件,NameNode經過查詢元數據,找到文件塊所在的DataNode地址。
2)挑選一臺DataNode(就近原則,而後隨機)服務器,請求讀取數據。
3)DataNode開始傳輸數據給客戶端(從磁盤裏面讀取數據輸入流,以Packet爲單位來作校驗)。
4)客戶端以Packet爲單位接收,先在本地緩存,而後寫入目標文件。
思考NameNode存儲在哪裏?
若是將NameNode節點元數據存於磁盤中,由於須要常常進行隨機訪問,且還響應客戶端的請求,效率低下。所以,要將元數據防於內存中,可是若是斷電,內存中的數據就會丟失,集羣沒法工做了。所以在磁盤中備份元數據的FsImage。
可是這樣會帶來新的問題就是,在更新內存中的數據同時,還要同時更新FsImage,這樣效率低下,所以,引入Edits文件(只進行追加操做,效率很高)。每當元數據有更新或者添加元數據時,修改內存中的元數據並追加到Edits中。這樣,一旦NameNode節點斷電,能夠經過FsImage和Edits的合併,合成元數據。
可是若是長時間添加數據到Edits中,致使文件過大,若是某天斷電,那麼回覆元數據時間很長,所以,須要按期合併FsImage和Edits文件,可是這個操做由NameNode節點完成,效率低下。所以引入新節點SecondaryNameNode,專門用於FsImage和Rdits按期合併。
NN和2NN工做機制如圖所示:
Fsimage:NameNode內存中元數據序列化後造成的文件。包含HDFS文件系統的全部目錄和文件inode的序列化信息;是HDFS文件系統元數據的永久性檢查點;
Edits:記錄客戶端更新--增刪改元數據信息的每一步操做。
NameNode啓動時,先滾動Edits並生成一個空的edits.inprogress,而後加載Edits和Fsimage到內存中,此時NameNode內存就持有最新的元數據信息。
1. 第一階段:NameNode啓動
(1)第一次啓動NameNode格式化後,建立Fsimage和Edits文件。若是不是第一次啓動,直接加載編輯日誌和鏡像文件到內存。
(2)客戶端對元數據進行增刪改的請求。
(3)NameNode記錄操做日誌,更新滾動日誌。
(4)NameNode在內存中對元數據進行增刪改。
2. 第二階段:Secondary NameNode工做
(1)Secondary NameNode詢問NameNode是否須要CheckPoint。直接帶回NameNode是否檢查結果。
(2)Secondary NameNode請求執行CheckPoint。
(3)NameNode滾動正在寫的Edits日誌。
(4)將滾動前的編輯日誌和鏡像文件拷貝到Secondary NameNode。
(5)Secondary NameNode加載編輯日誌和鏡像文件到內存,併合並。
(6)生成新的鏡像文件fsimage.chkpoint。
(7)拷貝fsimage.chkpoint到NameNode。
(8)NameNode將fsimage.chkpoint從新命名成fsimage。
NN和2NN工做的詳解:
Fsimage:NameNode內存中元數據序列化後造成的文件。 Edits:記錄客戶端更新元數據信息的每一步操做(可經過Edits運算出元數據)。 NameNode啓動時,先滾動Edits並生成一個空的edits.inprogress,而後加載Edits和Fsimage到內存中,此時NameNode內存就持有最新的元數據信息。Client開始對NameNode發送元數據的增刪改的請求,
這些請求的操做首先會被記錄到edits.inprogress中(查詢元數據的操做不會被記錄在Edits中,由於查詢操做不會更改元數據信息),若是此時NameNode掛掉,重啓後會從Edits中讀取元數據的信息。
而後,NameNode會在內存中執行元數據的增刪改的操做。因爲Edits中記錄的操做會愈來愈多,Edits文件會愈來愈大,致使NameNode在啓動加載Edits時會很慢,因此須要對Edits和Fsimage進行合併
(所謂合併,就是將Edits和Fsimage加載到內存中,照着Edits中的操做一步步執行,最終造成新的Fsimage)。SecondaryNameNode的做用就是幫助NameNode進行Edits和Fsimage的合併工做。
SecondaryNameNode首先會詢問NameNode是否須要CheckPoint(觸發CheckPoint須要知足兩個條件中的任意一個,定時時間到和Edits中數據寫滿了)。直接帶回NameNode是否檢查結果。
SecondaryNameNode執行CheckPoint操做,首先會讓NameNode滾動Edits並生成一個空的edits.inprogress,滾動Edits的目的是給Edits打個標記,之後全部新的操做都寫入edits.inprogress,
其餘未合併的Edits和Fsimage會拷貝到SecondaryNameNode的本地,而後將拷貝的Edits和Fsimage加載到內存中進行合併,生成fsimage.chkpoint,而後將fsimage.chkpoint拷貝給NameNode, 重命名爲Fsimage後替換掉原來的Fsimage。NameNode在啓動時就只須要加載以前未合併的Edits和Fsimage便可,由於合併過的Edits中的元數據信息已經被記錄在Fsimage中。
查看FsImage文件
[gll@hadoop101 current]$ ll 總用量 7256 -rw-rw-r--. 1 gll gll 1048576 1月 17 17:10 edits_0000000000000000001-0000000000000000001 -rw-rw-r--. 1 gll gll 42 1月 18 11:08 edits_0000000000000000002-0000000000000000003 -rw-rw-r--. 1 gll gll 1048576 1月 18 17:12 edits_0000000000000000004-0000000000000000020 -rw-rw-r--. 1 gll gll 1048576 1月 18 18:27 edits_0000000000000000021-0000000000000000021 -rw-rw-r--. 1 gll gll 42 1月 18 18:29 edits_0000000000000000022-0000000000000000023 -rw-rw-r--. 1 gll gll 3869 1月 18 19:29 edits_0000000000000000024-0000000000000000074 -rw-rw-r--. 1 gll gll 922 1月 18 20:29 edits_0000000000000000075-0000000000000000090 -rw-rw-r--. 1 gll gll 1048576 1月 18 20:37 edits_0000000000000000091-0000000000000000107 -rw-rw-r--. 1 gll gll 42 1月 19 11:28 edits_0000000000000000108-0000000000000000109 -rw-rw-r--. 1 gll gll 42 1月 19 12:28 edits_0000000000000000110-0000000000000000111 -rw-rw-r--. 1 gll gll 42 1月 19 13:28 edits_0000000000000000112-0000000000000000113 -rw-rw-r--. 1 gll gll 1276 1月 19 14:28 edits_0000000000000000114-0000000000000000127 -rw-rw-r--. 1 gll gll 42 1月 19 15:28 edits_0000000000000000128-0000000000000000129 -rw-rw-r--. 1 gll gll 42 1月 19 16:28 edits_0000000000000000130-0000000000000000131 -rw-rw-r--. 1 gll gll 1048576 1月 19 16:28 edits_0000000000000000132-0000000000000000132 -rw-rw-r--. 1 gll gll 1048576 1月 19 20:45 edits_0000000000000000133-0000000000000000133 -rw-rw-r--. 1 gll gll 14290 1月 20 12:24 edits_0000000000000000134-0000000000000000254 -rw-rw-r--. 1 gll gll 42 1月 20 13:24 edits_0000000000000000255-0000000000000000256 -rw-rw-r--. 1 gll gll 42 1月 20 14:24 edits_0000000000000000257-0000000000000000258 -rw-rw-r--. 1 gll gll 1048576 1月 20 14:24 edits_inprogress_0000000000000000259 -rw-rw-r--. 1 gll gll 2465 1月 20 13:24 fsimage_0000000000000000256 -rw-rw-r--. 1 gll gll 62 1月 20 13:24 fsimage_0000000000000000256.md5 -rw-rw-r--. 1 gll gll 2465 1月 20 14:24 fsimage_0000000000000000258 -rw-rw-r--. 1 gll gll 62 1月 20 14:24 fsimage_0000000000000000258.md5 -rw-rw-r--. 1 gll gll 4 1月 20 14:24 seen_txid -rw-rw-r--. 1 gll gll 206 1月 20 11:36 VERSION [gll@hadoop101 current]$ [gll@hadoop101 current]$ cat seen_txid //文件保存的是一個數字,就是最後一個edit_數字 [gll@hadoop101 current]$ hdfs oiv -p XML -i fsimage_0000000000000000258 -o /opt/module/hadoop-2.7.2/fsimage.xml [gll@hadoop101 current]$ sz /opt/module/hadoop-2.7.2/fsimage.xml
1)一般狀況下,SecondaryNameNode每隔一小時執行一次。
2)一分鐘檢查一次操做次數;
3 )當操做次數達到1百萬時,SecondaryNameNode執行一次。
方法一:將SecondaryNameNode中數據拷貝到NameNode存儲數據的目錄:可是這樣處理,2nn的數據有部分沒有合併,會不全,數據丟失。
1. kill -9 NameNode進程 2. 刪除NameNode存儲的數據(/opt/module/hadoop-2.7.2/data/tmp/dfs/name) [atguigu@hadoop102 hadoop-2.7.2]$ rm -rf /opt/module/hadoop-2.7.2/data/tmp/dfs/name/* 3. 拷貝SecondaryNameNode中數據到原NameNode存儲數據目錄 [atguigu@hadoop102 dfs]$ scp -r atguigu@hadoop104:/opt/module/hadoop-2.7.2/data/tmp/dfs/namesecondary/* ./name/ 4. 從新啓動NameNode [atguigu@hadoop102 hadoop-2.7.2]$ sbin/hadoop-daemon.sh start namenode
方法二:使用-importCheckpoint選項啓動NameNode守護進程,從而將SecondaryNameNode中數據拷貝到NameNode目錄中。
1.修改hdfs-site.xml中的 <property> <name>dfs.namenode.checkpoint.period</name> <value>120</value> </property> <property> <name>dfs.namenode.name.dir</name> <value>/opt/module/hadoop-2.7.2/data/tmp/dfs/name</value> </property> 2. kill -9 NameNode進程 3. 刪除NameNode存儲的數據(/opt/module/hadoop-2.7.2/data/tmp/dfs/name) [atguigu@hadoop102 hadoop-2.7.2]$ rm -rf /opt/module/hadoop-2.7.2/data/tmp/dfs/name/* 4. 若是SecondaryNameNode不和NameNode在一個主機節點上,須要將SecondaryNameNode存儲數據的目錄拷貝到NameNode存儲數據的平級目錄,並刪除in_use.lock文件 [atguigu@hadoop102 dfs]$ scp -r atguigu@hadoop104:/opt/module/hadoop-2.7.2/data/tmp/dfs/namesecondary ./ [atguigu@hadoop102 namesecondary]$ rm -rf in_use.lock [atguigu@hadoop102 dfs]$ pwd /opt/module/hadoop-2.7.2/data/tmp/dfs [atguigu@hadoop102 dfs]$ ls data name namesecondary 5. 導入檢查點數據(等待一會ctrl+c結束掉) [atguigu@hadoop102 hadoop-2.7.2]$ bin/hdfs namenode -importCheckpoint 6. 啓動NameNode [atguigu@hadoop102 hadoop-2.7.2]$ sbin/hadoop-daemon.sh start namenode
集羣處於安全模式,不能執行重要操做(寫操做)。集羣啓動完成後,自動退出安全模式。 (1)bin/hdfs dfsadmin -safemode get (功能描述:查看安全模式狀態) (2)bin/hdfs dfsadmin -safemode enter (功能描述:進入安全模式狀態) (3)bin/hdfs dfsadmin -safemode leave (功能描述:離開安全模式狀態) (4)bin/hdfs dfsadmin -safemode wait (功能描述:等待安全模式狀態)
1)一個數據塊在DataNode上以文件形式存儲在磁盤上,包括兩個文件,一個是數據自己,一個是元數據包括數據塊的長度,塊數據的校驗和,以及時間戳。
2)DataNode啓動後向NameNode註冊,經過後,週期性(1小時)的向NameNode上報全部的塊信息。
3)心跳是每3秒一次,心跳返回結果帶有NameNode給該DataNode的命令如複製塊數據到另外一臺機器,或刪除某個數據塊。若是超過10分鐘沒有收到某個DataNode的心跳,則認爲該節點不可用。
4)集羣運行中能夠安全加入和退出一些機器。
DataNode數據完整性
1)當DataNode讀取Block的時候,它會計算CheckSum。
2)若是計算後的CheckSum,與Block建立時值不同,說明Block已經損壞。
3)Client讀取其餘DataNode上的Block。
4)DataNode在其文件建立後周期驗證CheckSum,如圖3-16所示。
隨着公司業務的增加,數據量愈來愈大,原有的數據節點的容量已經不能知足存儲數據的需求,須要在原有集羣基礎上動態添加新的數據節點
1. 環境準備
(1)在hadoop104主機上再克隆一臺hadoop105主機
(2)修改IP地址和主機名稱
(3)刪除原來HDFS文件系統留存的文件(/opt/module/hadoop-2.7.2/data和log)
(4)source一下配置文件
[atguigu@hadoop105 hadoop-2.7.2]$ source /etc/profile
2. 服役新節點具體步驟
(1)直接啓動DataNode,便可關聯到集羣
[atguigu@hadoop105 hadoop-2.7.2]$ sbin/hadoop-daemon.sh start datanode
[atguigu@hadoop105 hadoop-2.7.2]$ sbin/yarn-daemon.sh start nodemanager
(2)在hadoop105上上傳文件
[atguigu@hadoop105 hadoop-2.7.2]$ hadoop fs -put /opt/module/hadoop-2.7.2/LICENSE.txt /
(3)若是數據不均衡,能夠用命令實現集羣的再平衡
[atguigu@hadoop102 sbin]$ ./start-balancer.sh
starting balancer, logging to /opt/module/hadoop-2.7.2/logs/hadoop-atguigu-balancer-hadoop102.out
添加到白名單的主機節點,都容許訪問NameNode,不在白名單的主機節點,都會被退出。
配置白名單的具體步驟以下:
(1)在NameNode的/opt/module/hadoop-2.7.2/etc/hadoop目錄下建立dfs.hosts文件 [atguigu@hadoop102 hadoop]$ pwd /opt/module/hadoop-2.7.2/etc/hadoop [atguigu@hadoop102 hadoop]$ touch dfs.hosts [atguigu@hadoop102 hadoop]$ vi dfs.hosts 添加以下主機名稱(不添加hadoop105) hadoop102 hadoop103 hadoop104 (2)在NameNode的hdfs-site.xml配置文件中增長dfs.hosts屬性 <property> <name>dfs.hosts</name> <value>/opt/module/hadoop-2.7.2/etc/hadoop/dfs.hosts</value> </property> (3)配置文件分發 [atguigu@hadoop102 hadoop]$ xsync hdfs-site.xml (4)刷新NameNode [atguigu@hadoop102 hadoop-2.7.2]$ hdfs dfsadmin -refreshNodes Refresh nodes successful (5)更新ResourceManager節點 [atguigu@hadoop102 hadoop-2.7.2]$ yarn rmadmin -refreshNodes 17/06/24 14:17:11 INFO client.RMProxy: Connecting to ResourceManager at hadoop103/192.168.1.103:8033
在黑名單上面的主機都會被強制退出
1.在NameNode的/opt/module/hadoop-2.7.2/etc/hadoop目錄下建立dfs.hosts.exclude文件
[atguigu@hadoop102 hadoop]$ pwd /opt/module/hadoop-2.7.2/etc/hadoop [atguigu@hadoop102 hadoop]$ touch dfs.hosts.exclude [atguigu@hadoop102 hadoop]$ vi dfs.hosts.exclude 添加以下主機名稱(要退役的節點) hadoop105
2.在NameNode的hdfs-site.xml配置文件中增長dfs.hosts.exclude屬性
<property> <name>dfs.hosts.exclude</name> <value>/opt/module/hadoop-2.7.2/etc/hadoop/dfs.hosts.exclude</value> </property>
3.刷新NameNode、刷新ResourceManager
[atguigu@hadoop102 hadoop-2.7.2]$ hdfs dfsadmin -refreshNodes Refresh nodes successful [atguigu@hadoop102 hadoop-2.7.2]$ yarn rmadmin -refreshNodes 17/06/24 14:55:56 INFO client.RMProxy: Connecting to ResourceManager at hadoop103/192.168.1.103:8033
4. 檢查Web瀏覽器,退役節點的狀態爲decommission in progress(退役中),說明數據節點正在複製塊到其餘節點,如圖3-17所示
5.等待退役節點狀態爲decommissioned(全部塊已經複製完成),中止該節點及節點資源管理器。注意:若是副本數是3,服役的節點小於等於3,是不能退役成功的,須要修改副本數後才能退役,如圖3-18所示
[atguigu@hadoop105 hadoop-2.7.2]$ sbin/hadoop-daemon.sh stop datanode stopping datanode [atguigu@hadoop105 hadoop-2.7.2]$ sbin/yarn-daemon.sh stop nodemanager stopping nodemanager
6. 若是數據不均衡,能夠用命令實現集羣的再平衡
[atguigu@hadoop102 hadoop-2.7.2]$ sbin/start-balancer.sh starting balancer, logging to /opt/module/hadoop-2.7.2/logs/hadoop-atguigu-balancer-hadoop102.out Time Stamp Iteration# Bytes Already Moved Bytes Left To Move Bytes Being Moved
注意:不容許白名單和黑名單中同時出現同一個主機名稱。
1. DataNode也能夠配置成多個目錄,每一個目錄存儲的數據不同。即:數據不是副本
2.具體配置以下
hdfs-site.xml <property> <name>dfs.datanode.data.dir</name> <value>file:///${hadoop.tmp.dir}/dfs/data1,file:///${hadoop.tmp.dir}/dfs/data2</value> </property>
1.scp實現兩個遠程主機之間的文件複製 scp -r hello.txt root@hadoop103:/user/atguigu/hello.txt // 推 push scp -r root@hadoop103:/user/atguigu/hello.txt hello.txt // 拉 pull scp -r root@hadoop103:/user/atguigu/hello.txt root@hadoop104:/user/atguigu //是經過本地主機中轉實現兩個遠程主機的文件複製;若是在兩個遠程主機之間ssh沒有配置的狀況下可使用該方式。 2.採用distcp命令實現兩個Hadoop集羣之間的遞歸數據複製 [atguigu@hadoop102 hadoop-2.7.2]$ bin/hadoop distcp hdfs://haoop102:9000/user/atguigu/hello.txt hdfs://hadoop103:9000/user/atguigu/hello.txt
案例實操
(1)須要啓動YARN進程
[atguigu@hadoop102 hadoop-2.7.2]$ start-yarn.sh
(2)歸檔文件
把/user/atguigu/input目錄裏面的全部文件歸檔成一個叫input.har的歸檔文件,並把歸檔後文件存儲到/user/atguigu/output路徑下。
[atguigu@hadoop102 hadoop-2.7.2]$ bin/hadoop archive -archiveName input.har –p /user/atguigu/input /user/atguigu/output
(3)查看歸檔
[atguigu@hadoop102 hadoop-2.7.2]$ hadoop fs -lsr /user/atguigu/output/input.har
[atguigu@hadoop102 hadoop-2.7.2]$ hadoop fs -lsr har:///user/atguigu/output/input.har
(4)解歸檔文件
[atguigu@hadoop102 hadoop-2.7.2]$ hadoop fs -cp har:/// user/atguigu/output/input.har/* /user/atguigu
1)所謂HA(High Available),即高可用(7*24小時中段服務)
2)實現高可用最關鍵的策略是消除單點故障。HA嚴格來講應該分紅各個組件的HA機制:HDFS的HA和YARN的HA。
3)Hadoop2.0以前,在HDFS集羣中NameNode存在單點故障(SPOF)。
4) NameNode主要在如下兩個方面影響HDFS集羣
HDFS HA功能經過配置Active/Standby兩個NameNodes實現在集羣中對NameNode的熱備來解決上述問題。若是出現故障,如機器崩潰或機器須要升級維護,這時可經過此種方式將NameNode很快的切換到另一臺機器。
經過雙NameNode消除單點故障
1. 元數據管理方式須要改變
內存中各自保存一份元數據;
Edits日誌只有Active狀態的NameNode節點能夠作寫操做;
兩個NameNode均可以讀取Edits;
共享的Edits放在一個共享存儲中管理(qjournal和NFS兩個主流實現);
2. 須要一個狀態管理功能模塊
實現了一個zkfailover,常駐在每個namenode所在的節點,每個zkfailover負責監控本身所在NameNode節點,利用zk進行狀態標識,當須要進行狀態切換時,由zkfailover來負責切換,切換時須要防止brain split現象的發生。
3. 必須保證兩個NameNode之間可以ssh無密碼登陸
4. 隔離(Fence),即同一時刻僅僅有一個NameNode對外提供服務
故障轉移增長了zookeeper和ZKFS進程
Zookeeper:維護少許協調數據,通知客戶端這些數據的改變和監視客戶端故障的高可用服務
HA依賴zookeeper的一下功能:
1)故障檢測:集羣中的每一個NameNode在ZooKeeper中維護了一個持久會話,若是機器崩潰,ZooKeeper中的會話將終止,ZooKeeper通知另外一個NameNode須要觸發故障轉移。
2)現役NameNode選擇:ZooKeeper提供了一個簡單的機制用於惟一的選擇一個節點爲active狀態。若是目前現役NameNode崩潰,另外一個節點可能從ZooKeeper得到特殊的排外鎖以代表它應該成爲現役NameNode。
ZKFC是自動故障轉移中的另外一個新組件,是ZooKeeper的客戶端,也監視和管理NameNode的狀態。每一個運行NameNode的主機也運行了一個ZKFC進程,ZKFC負責:
1)健康監測:ZKFC使用一個健康檢查命令按期地ping與之在相同主機的NameNode,只要該NameNode及時地回覆健康狀態,ZKFC認爲該節點是健康的。若是該節點崩潰,凍結或進入不健康狀態,健康監測器標識該節點爲非健康的。
2)ZooKeeper會話管理:當本地NameNode是健康的,ZKFC保持一個在ZooKeeper中打開的會話。若是本地NameNode處於active狀態,ZKFC也保持一個特殊的znode鎖,該鎖使用了ZooKeeper對短暫節點的支持,若是會話終止,鎖節點將自動刪除。
3)基於ZooKeeper的選擇:若是本地NameNode是健康的,且ZKFC發現沒有其它的節點當前持有znode鎖,它將爲本身獲取該鎖。若是成功,則它已經贏得了選擇,並負責運行故障轉移進程以使它的本地NameNode爲Active。故障轉移進程與前面描述的手動故障轉移類似,首先若是必要保護以前的現役NameNode,而後本地NameNode轉換爲Active狀態。
ZKFC:是zookeeper的客戶端,讓它聯繫zookeeper,HA是hadoop2.0纔有的,namenode在1.0時就有了,可是爲了保持NameNode的健壯性,未把ZKFC加入NameNode中,可是兩個進程是相互綁定的,有ZKFC監視NameNode,
將狀態彙報給zookeeper。
主Namenode處理全部的操做請求(讀寫),而Standby只是做爲slave,維護儘量同步的狀態,使得故障時可以快速切換到Standby。爲了使Standby Namenode與Active Namenode數據保持同步,兩個Namenode都與一組Journal Node進行通訊。當主Namenode進行任務的namespace操做時,都會確保持久會修改日誌到Journal Node節點中的大部分。Standby Namenode持續監控這些edit,當監測到變化時,將這些修改應用到本身的namespace
當進行故障轉移時,Standby在成爲Active Namenode以前,會確保本身已經讀取了Journal Node中的全部edit日誌,從而保持數據狀態與故障發生前一致。
腦裂現象(split brain): 當兩臺Namenode都認爲本身的Active Namenode時,會同時嘗試寫入數據(不會再去檢測和同步數據):zookeeper會根據自身通知機制,確認主機,防止腦裂。
若是一臺出現了假死,當前NameNode監控的ZKFX檢測到假死,會通知從機的ZKFC,從而殺死假死的NameNode的進程,激活從機爲Active,同時通知zookeeper服務端將從機註冊爲Active。
如今合併fsimage是由standby來完成的,沒有secondaryNameNode;
Journal Nodes爲了防止腦裂,只讓一個Namenode寫入數據,內部經過維護epoch數來控制,從而安全地進行故障轉移,有兩種方式共享edits log:
如圖所示,NFS做爲主備Namenode的共享存儲。這種方案可能會出現腦裂(split-brain),即兩個節點都認爲本身是主Namenode並嘗試向edit log寫入數據,這可能會致使數據損壞。經過配置fencin腳原本解決這個問題,fencing腳本用於:
將以前的Namenode關機
禁止以前的Namenode繼續訪問共享的edit log文件
使用這種方案,管理員就能夠手工觸發Namenode切換,而後進行升級維護。但這種方式存在如下問題:
- 只能手動進行故障轉移,每次故障都要求管理員採起措施切換。
- NAS/SAN設置部署複雜,容易出錯,且NAS自己是單點故障。
- Fencing 很複雜,常常會配置錯誤。
- 沒法解決意外(unplanned)事故,如硬件或者軟件故障。
所以須要另外一種方式來處理這些問題:
QJM(Quorum Journal Manager)是Hadoop專門爲Namenode共享存儲開發的組件。其集羣運行一組Journal Node,每一個Journal 節點暴露一個簡單的RPC接口,容許Namenode讀取和寫入數據,數據存放在Journal節點的本地磁盤。當Namenode寫入edit log時,它向集羣的全部Journal Node發送寫入請求,當多數節點回復確認成功寫入以後,edit log就認爲是成功寫入。例若有3個Journal Node,Namenode若是收到來自2個節點的確認消息,則認爲寫入成功。
而在故障自動轉移的處理上,引入了監控Namenode狀態的ZookeeperFailController(ZKFC)。ZKFC通常運行在Namenode的宿主機器上,與Zookeeper集羣協做完成故障的自動轉移。整個集羣架構圖以下:
Namenode使用QJM 客戶端提供的RPC接口與Namenode進行交互。寫入edit log時採用基於仲裁的方式,即數據必須寫入JournalNode集羣的大部分節點。
在Journal Node節點上(服務端)
服務端Journal運行輕量級的守護進程,暴露RPC接口供客戶端調用。實際的edit log數據保存在Journal Node本地磁盤,該路徑在配置中使用dfs.journalnode.edits.dir屬性指定。
Journal Node經過epoch數來解決腦裂的問題,稱爲JournalNode fencing。具體工做原理以下:
1)當Namenode變成Active狀態時,被分配一個整型的epoch數,這個epoch數是獨一無二的,而且比以前全部Namenode持有的epoch number都高。
2)當Namenode向Journal Node發送消息的時候,同時也帶上了epoch。當Journal Node收到消息時,將收到的epoch數與存儲在本地的promised epoch比較,若是收到的epoch比本身的大,則使用收到的epoch更新本身本地的epoch數。若是收到的比本地的epoch小,則拒絕請求。
3)edit log必須寫入大部分節點纔算成功,也就是其epoch要比大多數節點的epoch高。
這種方式解決了NFS方式的3個問題:
不須要額外的硬件,使用原有的物理機
Fencing經過epoch數來控制,避免出錯。
自動故障轉移:Zookeeper處理該問題。
HDFS-HA故障轉移參考:http://www.javashuo.com/article/p-xlfrzyaa-ca.html
1. 修改IP
2. 修改主機名及主機名和IP地址的映射
3. 關閉防火牆
4. ssh免密登陸
5. 安裝JDK,配置環境變量等
hadoop102 |
hadoop103 |
hadoop104 |
NameNode |
NameNode |
|
JournalNode |
JournalNode |
JournalNode |
DataNode |
DataNode |
DataNode |
ZK |
ZK |
ZK |
|
ResourceManager |
|
NodeManager |
NodeManager |
NodeManager |
在opt目錄下建立一個ha文件夾 mkdir ha
將/opt/app/下的 hadoop-2.7.2拷貝到/opt/ha目錄下 cp -r hadoop-2.7.2/ /opt/ha/
配置hadoop-env.sh export JAVA_HOME=/opt/module/jdk1.8.0_144
配置core-site.xml
<configuration> <!-- 把兩個NameNode)的地址組裝成一個集羣mycluster --> <property> <name>fs.defaultFS</name> <value>hdfs://mycluster</value> </property> <!-- 指定hadoop運行時產生文件的存儲目錄 --> <property> <name>hadoop.tmp.dir</name> <value>/opt/ha/hadoop-2.7.2/data/tmp</value> </property> </configuration>
配置hdfs-site.xml
<configuration> <!-- 徹底分佈式集羣名稱 --> <property> <name>dfs.nameservices</name> <value>mycluster</value> </property> <!-- 集羣中NameNode節點都有哪些 --> <property> <name>dfs.ha.namenodes.mycluster</name> <value>nn1,nn2</value> </property> <!-- nn1的RPC通訊地址 --> <property> <name>dfs.namenode.rpc-address.mycluster.nn1</name> <value>hadoop102:9000</value> </property> <!-- nn2的RPC通訊地址 --> <property> <name>dfs.namenode.rpc-address.mycluster.nn2</name> <value>hadoop103:9000</value> </property> <!-- nn1的http通訊地址 --> <property> <name>dfs.namenode.http-address.mycluster.nn1</name> <value>hadoop102:50070</value> </property> <!-- nn2的http通訊地址 --> <property> <name>dfs.namenode.http-address.mycluster.nn2</name> <value>hadoop103:50070</value> </property> <!-- 指定NameNode元數據在JournalNode上的存放位置 --> <property> <name>dfs.namenode.shared.edits.dir</name> <value>qjournal://hadoop102:8485;hadoop103:8485;hadoop104:8485/mycluster</value> </property> <!-- 配置隔離機制,即同一時刻只能有一臺服務器對外響應 --> <property> <name>dfs.ha.fencing.methods</name> <value>sshfence</value> </property> <!-- 使用隔離機制時須要ssh無祕鑰登陸--> <property> <name>dfs.ha.fencing.ssh.private-key-files</name> <value>/home/atguigu/.ssh/id_rsa</value> </property> <!-- 聲明journalnode服務器存儲目錄--> <property> <name>dfs.journalnode.edits.dir</name> <value>/opt/ha/hadoop-2.7.2/data/jn</value> </property> <!-- 關閉權限檢查--> <property> <name>dfs.permissions.enable</name> <value>false</value> </property> <!-- 訪問代理類:client,mycluster,active配置失敗自動切換實現方式--> <property> <name>dfs.client.failover.proxy.provider.mycluster</name> <value>org.apache.hadoop.hdfs.server.namenode.ha.ConfiguredFailoverProxyProvider</value> </property> </configuration>
拷貝配置好的hadoop環境到其餘節點
1. 在各個JournalNode節點上,輸入如下命令啓動journalnode服務 sbin/hadoop-daemon.sh start journalnode 2. 在[nn1]上,對其進行格式化,並啓動 bin/hdfs namenode -format sbin/hadoop-daemon.sh start namenode 3. 在[nn2]上,同步nn1的元數據信息 bin/hdfs namenode -bootstrapStandby 4. 啓動[nn2] sbin/hadoop-daemon.sh start namenode 5. 在[nn1]上,啓動全部datanode sbin/hadoop-daemons.sh start datanode 6. 將[nn1]切換爲Active bin/hdfs haadmin -transitionToActive nn1 7. 查看是否Active bin/hdfs haadmin -getServiceState nn1
1. 具體配置
(1)在hdfs-site.xml中增長
<property> <name>dfs.ha.automatic-failover.enabled</name> <value>true</value> </property>
(2)在core-site.xml文件中增長
<property> <name>ha.zookeeper.quorum</name> <value>hadoop102:2181,hadoop103:2181,hadoop104:2181</value> </property>
2. 啓動
(1)關閉全部HDFS服務: sbin/stop-dfs.sh (2)啓動Zookeeper集羣: bin/zkServer.sh start (3)初始化HA在Zookeeper中狀態: bin/hdfs zkfc -formatZK (4)啓動HDFS服務: sbin/start-dfs.sh
3.驗證
(1)將Active NameNode進程kill kill -9 namenode的進程id
(2)將Active NameNode機器斷開網絡 service network stop
YARN-HA工做機制,如圖3-23所示:
(1)yarn-site.xml
<configuration> <property> <name>yarn.nodemanager.aux-services</name> <value>mapreduce_shuffle</value> </property> <!--啓用resourcemanager ha--> <property> <name>yarn.resourcemanager.ha.enabled</name> <value>true</value> </property> <!--聲明兩臺resourcemanager的地址--> <property> <name>yarn.resourcemanager.cluster-id</name> <value>cluster-yarn1</value> </property> <property> <name>yarn.resourcemanager.ha.rm-ids</name> <value>rm1,rm2</value> </property> <property> <name>yarn.resourcemanager.hostname.rm1</name> <value>hadoop102</value> </property> <property> <name>yarn.resourcemanager.hostname.rm2</name> <value>hadoop103</value> </property> <!--指定zookeeper集羣的地址--> <property> <name>yarn.resourcemanager.zk-address</name> <value>hadoop102:2181,hadoop103:2181,hadoop104:2181</value> </property> <!--啓用自動恢復--> <property> <name>yarn.resourcemanager.recovery.enabled</name> <value>true</value> </property> <!--指定resourcemanager的狀態信息存儲在zookeeper集羣--> <property> <name>yarn.resourcemanager.store.class</name>
<value>org.apache.hadoop.yarn.server.resourcemanager.recovery.ZKRMStateStore</value> </property> </configuration>
(1)在各個JournalNode節點上,輸入如下命令啓動journalnode服務: sbin/hadoop-daemon.sh start journalnode (2)在[nn1]上,對其進行格式化,並啓動: bin/hdfs namenode -format sbin/hadoop-daemon.sh start namenode (3)在[nn2]上,同步nn1的元數據信息: bin/hdfs namenode -bootstrapStandby (4)啓動[nn2]: sbin/hadoop-daemon.sh start namenode (5)啓動全部DataNode sbin/hadoop-daemons.sh start datanode (6)將[nn1]切換爲Active bin/hdfs haadmin -transitionToActive nn1
(1)在hadoop102中執行: sbin/start-yarn.sh (2)在hadoop103中執行: sbin/yarn-daemon.sh start resourcemanager (3)查看服務狀態,如圖3-24所示 bin/yarn rmadmin -getServiceState rm1