隨着數據量愈來愈大,在一個操做系統存不下全部的數據,那麼就分配到更多的操做系統管理的磁盤中,可是不方便管理和維護,迫切須要一種系統來管理多臺機器上的文件,這就是分佈式文件管理系統。HDFS只是分佈式文件管理系統中的一種。java
HDFS(Hadoop Distributed File System),它是一個文件系統,用於存儲文件,經過目錄樹來定位文件;其次,它是分佈式的,由不少服務器聯合起來實現其功能,集羣中的服務器有各自的角色。node
HDFS的使用場景:適合一次寫入,屢次讀出的場景,且不支持文件的修改。適合用來作數據分析,並不適合用來作網盤應用。apache
優勢:緩存
缺點:安全
HDFS 中的文件在物理上是分塊存儲(Block),塊的大小能夠經過配置參數(dfs.blocksize)來規定,默認大小在Hadoop2.x 版本中是 128M,老版本中是 64M。服務器
若是尋址時間爲 100ms,即查找目標 Block 的時間是 100ms。網絡
尋址時間與傳輸時間的比例爲 100 : 1爲最佳狀態,所以傳輸時間爲 1ms。架構
目前磁盤的傳輸速率大概在 100MB/s,取個整大概就是 128MB。併發
(1)-help:輸出這個命令參數app
(2)-ls:顯示目錄信息
(3)-mkdir:在 HDFS 上建立目錄
(4)-moveFromLocal:從本地剪切粘貼到 HDFS
(5)-appendToFile:追加一個文件到已經存在的文件末尾
(6)-cat:顯示文件內容
(7)-chgrp 、-chmod、-chown:Linux 文件系統中的用法同樣,修改文件所屬權限
(8)-copyFromLocal:從本地文件系統中拷貝文件到 HDFS 路徑去
(9)-copyToLocal:從 HDFS 拷貝到本地
(10)-cp :從 HDFS 的一個路徑拷貝到 HDFS 的另外一個路徑
(11)-mv:在 HDFS 目錄中移動文件
(12)-get:等同於 copyToLocal,就是從 HDFS 下載文件到本地
(13)-getmerge:合併下載多個文件,好比 HDFS 的目錄 /user/djm/test 下有多個文件:log.1, log.2,log.3,...
(14)-put:等同於 copyFromLocal
(15)-tail:顯示一個文件的末尾
(16)-rm:刪除文件或文件夾
(17)-rmdir:刪除空目錄
(18)-du:統計文件夾的大小信息
(19)-setrep:設置 HDFS 中文件的副本數量
package com.djm.hdfsclient; import org.apache.hadoop.conf.Configuration; import org.apache.hadoop.fs.*; import org.junit.After; import org.junit.Before; import org.junit.Test; import java.io.IOException; import java.net.URI; public class HdfsClient { FileSystem fileSystem = null; @Before public void init() { try { fileSystem = FileSystem.get(URI.create("hdfs://hadoop102:9000"), new Configuration(), "djm"); } catch (IOException e) { e.printStackTrace(); } catch (InterruptedException e) { e.printStackTrace(); } } /** * 上傳文件 */ @Test public void put() { try { fileSystem.copyFromLocalFile(new Path("C:\\Users\\Administrator\\Desktop\\Hadoop 入門.md"), new Path("/")); } catch (IOException e) { e.printStackTrace(); } } /** * 下載文件 */ @Test public void download() { try { // useRawLocalFileSystem表示是否開啓文件校驗 fileSystem.copyToLocalFile(false, new Path("/Hadoop 入門.md"), new Path("C:\\Users\\Administrator\\Desktop\\Hadoop 入門1.md"), true); } catch (IOException e) { e.printStackTrace(); } } /** * 刪除文件 */ @Test public void delete() { try { // recursive表示是否遞歸刪除 fileSystem.delete(new Path("/Hadoop 入門.md"), true); } catch (IOException e) { e.printStackTrace(); } } /** * 文件重命名 */ @Test public void rename() { try { fileSystem.rename(new Path("/tmp"), new Path("/temp")); } catch (IOException e) { e.printStackTrace(); } } /** * 查看文件信息 */ @Test public void ls() { try { RemoteIterator<locatedfilestatus> listFiles = fileSystem.listFiles(new Path("/etc"), true); while (listFiles.hasNext()) { LocatedFileStatus fileStatus = listFiles.next(); if (fileStatus.isFile()) { // 僅輸出文件信息 System.out.print(fileStatus.getPath().getName() + " " + fileStatus.getLen() + " " + fileStatus.getPermission() + " " + fileStatus.getGroup() + " "); // 獲取文件塊信息 BlockLocation[] blockLocations = fileStatus.getBlockLocations(); for (BlockLocation blockLocation : blockLocations) { // 獲取節點信息 String[] hosts = blockLocation.getHosts(); for (String host : hosts) { System.out.print(host + " "); } } System.out.println(); } } } catch (IOException e) { e.printStackTrace(); } } @After public void exit() { try { fileSystem.close(); } catch (IOException e) { e.printStackTrace(); } } }
一、客戶端經過 Distributed FileSystem 模塊向 NameNode 請求上傳文件,NameNode 檢查目標文件是否已存在,父目錄是否存在。
二、NameNode 返回是否能夠上傳。
三、客戶端請求第一個 Block 上傳到哪幾個 DataNode。
四、NameNode 返回三個節點,分別是 dn一、dn二、dn3。
五、客戶端經過 FSDataOutputStream 模塊請求 dn1 上傳數據,dn1 收到請求會繼續調用 dn2,而後 dn2 調用 dn3,將這個通訊管道創建完成。
六、按倒序逐級響應客戶端。
七、客戶端開始往 dn1 上傳第一個 Block(先從磁盤讀取數據放到一個本地內存緩存),以 Packet 爲單位,dn1 收到一個Packet 就會傳給 dn2,dn2 傳給 dn3;dn1 每傳一個 packet 會放入一個應答隊列等待應答。
八、當一個Block傳輸完成以後,客戶端再次請求NameNode上傳第二個Block的服務器。
在HDFS寫數據的過程當中,NameNode會選擇距離待上傳數據最近距離的DataNode接收數據。那麼這個最近距離怎麼計算呢?
一、客戶端經過 Distributed FileSystem 向 NameNode 請求下載文件,NameNode經過查詢元數據,找到文件塊所在的DataNode地址。
二、根據就近原則挑選一臺 DataNode,請求讀取數據。
三、DataNode 開始傳輸數據給客戶端。
四、客戶端以 Packet 爲單位接收,先在本地緩存,而後寫入目標文件。
若是存儲在 NameNode 節點的磁盤中,由於常常須要進行隨機訪問,還有響應客戶請求,必然是效率太低,所以,元數據必須存放在內存中,周所周知,內存的特色是速度快,斷電後丟失數據,一旦斷電,元數據丟失,整個集羣就沒法工做了,所以產生了用於備份元數據的 FsImage。
可是這樣又會引起一個問題,當內存中的元數據更新時,FsImage 是否要同時更新,若是要同步更新,就會致使效率低,若是不一樣步更新,就會致使數據一致性問題,一旦忽然斷電,就會丟失一部分數據,所以,引入了 Edits(只進行追加操做,效率很高),每當元數據進行增長或者修改時,先追加到 Edits,在修改內存,這樣的話,一旦斷電,能夠經過 FsImage 和 Edits 合成元數據。
可是,若是長時間添加數據到 Edits,致使 Edits 過大,仍是會影響效率,並且一旦斷電,恢復元數據的時間也會相應增長,所以,須要按期的對 FsImage 和 Edits 進行合併,若是這個操做由 NameNode 去完成,又會效率低(由於在合併後不能處理寫請求),因此引入了 SecondaryNameNode,專門用來作合併操做。
NameNode 工做:
一、第一次啓動 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。
oiv 查看Fsimage 文件
oev 查看 Edits 文件
知足如下兩個條件都會觸發合併操做:
一般狀況下,SecondaryNameNode 每隔一小時執行一次。
[hdfs-default.xml]
<property> <name>dfs.namenode.checkpoint.period</name> <value>3600</value> </property>
一分鐘檢查一次操做次數,當次數到達 100 萬次就會觸發操做。
[hdfs-default.xml]
<property> <name>dfs.namenode.checkpoint.txns</name> <value>1000000</value> <description>操做動做次數</description> </property> <property> <name>dfs.namenode.checkpoint.check.period</name> <value>60</value> <description> 1分鐘檢查一次操做次數</description> </property>
NameNode 故障後,能夠採用以下兩種方法恢復數據:
將 2NN 中的數據拷貝到 NN 存儲數據的目錄。
使用 -importCheckpoint 選項啓動 NN 守護進程,從而將 2NN 中數據拷貝到 NN 目錄中。
基本命令:
hdfs dfsadmin -safemode get:查看安全模式狀態
hdfs dfsadmin -safemode enter:進入安全模式狀態
hdfs dfsadmin -safemode leave:離開安全模式狀態
hdfs dfsadmin -safemode wait:等待安全模式狀態
一、一個數據塊在 DataNode 上以文件形式存儲在磁盤上,包括兩個文件,一個是數據自己,一個是元數據包括數據塊的長度,塊數據的校驗和,以及時間戳。
二、DataNode 啓動後向 NameNode 註冊,經過後,週期性(1小時)的向 NameNode 上報全部的塊信息。
三、心跳是每 3 秒一次,心跳返回結果帶有 NameNode 給該 DataNode 的命令如複製塊數據到另外一臺機器,或刪除某個數據塊,若是超過 10 分鐘沒有收到某個 DataNode 的心跳,則認爲該節點不可用。
四、集羣運行中能夠安全加入和退出一些機器。
一、當 DataNode 讀取 Block 的時候,它會計算 CheckSum。
二、若是計算後的 CheckSum,與 Block 建立時值不同,說明 Block 已經損壞。
三、Client 讀取其餘 DataNode 上的 Block。
四、在其文件建立後周期驗證。
[hdfs-site.xml]
<property> <name>dfs.namenode.heartbeat.recheck-interval</name> <value>300000</value> <description>毫秒</description> </property> <property> <name>dfs.heartbeat.interval</name> <value>3</value> <description>秒</description> </property>
將 hadoop102 上的 java、hadoop、profile 發送到新主機,source 一下 profile,直接啓動便可加入集羣。
建立黑名單
[djm@hadoop101 hadoop]$ touch blacklist
配置加入黑名單的主機
hadoop102
配置 hdfs-site.xml
<property> <name>dfs.hosts.exclude</name> <value>/opt/module/hadoop-2.7.2/etc/hadoop/blacklist</value> </property>
刷新 namenodes
[djm@hadoop102 hadoop-2.7.2]$ hdfs dfsadmin -refreshNodes
更新 ResourceManager 節點
[djm@hadoop102 hadoop-2.7.2]$ yarn rmadmin -refreshNodes
若是數據不均衡,能夠用命令實現集羣的再平衡
[djm@hadoop102 hadoop-2.7.2]$ start-balancer.sh
建立白名單
[djm@hadoop101 hadoop]$ touch whitelist
配置加入黑名單的主機
hadoop102 hadoop103 hadoop104
配置 hdfs-site.xml
<property> <name>dfs.hosts</name> <value>/opt/module/hadoop-2.7.2/etc/hadoop/whitelist</value> </property>
刷新 namenodes
[djm@hadoop102 hadoop-2.7.2]$ hdfs dfsadmin -refreshNodes
更新 ResourceManager 節點
[djm@hadoop102 hadoop-2.7.2]$ yarn rmadmin -refreshNodes
若是數據不均衡,能夠用命令實現集羣的再平衡
[djm@hadoop102 hadoop-2.7.2]$ start-balancer.sh
黑白名單的區別:
白名單比較嚴格,黑名單比較平緩,處於黑名單中的主機會同步數據結束後繼續處於集羣,只是不在處理請求而已,而不處於白名單中的主機會直接被幹掉。
DataNode也能夠配置成多個目錄,每一個目錄存儲的數據不同,即:數據不是副本。
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>
採用 distcp 命令實現兩個 Hadoop 集羣之間的遞歸數據複製
[djm@hadoop102 hadoop-2.7.2]$ hadoop distcp hdfs://haoop102:9000/user/djm/hello.txt hdfs://hadoop103:9000/user/djm/hello.txt
歸檔文件
[djm@hadoop102 hadoop-2.7.2]$ hadoop archive -archiveName input.har –p /user/djm/input /user/djm/output
查看歸檔
[djm@hadoop102 hadoop-2.7.2]$ hadoop fs -lsr har:///user/djm/output/input.har
解歸檔文件
[atguigu@djm hadoop-2.7.2]$ hadoop fs -cp har:/// user/djm/output/input.har/* /user/djm
</locatedfilestatus>