HDFS 基於流數據模式訪問和處理超大文件的需求而開發的。 低延時的數據訪問 HDFS是為高吞吐數據傳輸設計的,因此可能犧牲延時HBase更適合低延時的數據訪問。 大量小文件 文件的元數據保存在NameNode的記憶體中, 整個文件系統的文件數量會受限於NameNode的記憶體大小。 多方讀寫,需要任意 ...
基於流數據模式訪問和處理超大文件的需求而開發的。
HDFS不適合的應用類型
-
低延時的數據訪問
HDFS是為高吞吐數據傳輸設計的,因此可能犧牲延時HBase更適合低延時的數據訪問。
-
文件的元數據保存在NameNode的記憶體中, 整個文件系統的文件數量會受限於NameNode的記憶體大小。
-
多方讀寫,需要任意的文件修改
HDFS採用追加的方式寫入數據。不支持文件任意修改。不支持多個寫入器(writer)。
相關概念
塊(Block)
HDFS文件系統的文件被分成塊進行存儲;HDFS被設計出來就是處理大文件的;
塊預設大小:64M;小於一個塊大小的文件不會占據整個塊的空間;
好處:
-
它將超大文件分成眾多塊,分別存儲在集群的各個機器上;
-
簡化存儲系統:塊的大小固定,更利於管理,複製,備份,容錯,並且便於元數據去統計、映射;
塊的大小可以自行設置,但是必須是64M的整數倍(hdfs-site.xml)
<property> <name>dfs.block.size</name> <value>512000</value> </property>
為什麼塊要設置這麼大?
目的是:最小化定址開銷
比如:定址時間需要10ms
1.塊=1M,定址64M文件,需要640ms
2.塊=64M,需要10ms
塊的設置不能太大,因為MapReduce任務是按塊來處理的,塊太大,任務少,作業效率就低了;
從用戶角度看,存儲一個文件在HDFS上,是通過NameNode看到的
從內部角度看,文件被切分之後存儲在多個DataNode上,元數據存儲在NameNode;
塊存儲位置:在datanode目錄下
每個塊由兩個文件組成:文件信息和meta校驗信息
-rw-r--r-- 1 root root 355 9月 10 18:21 blk_1073741839
-rw-r--r-- 1 root root 11 9月 10 18:21 blk_1073741839_1015.meta
NameNode
NameNode、DataNode分別承擔Master、Worker的角色;
作用:
-
維護元數據信息(記憶體);即:管理文件的命名空間(哪個文件在哪個DataNode)
-
維護文件系統樹及整棵樹內的所有文件和目錄(磁碟);通過這兩個文件來管理
-
命名空間鏡像文件(NameSpace image)
-
編輯日誌文件(Edit log):只有4M
(存放目錄:hadoop/data/tmp/dfs/name/current/)
-
-
響應客戶端請求(記憶體);
元數據形式:
存放目錄:
# 目錄 副本數 Block數 每個Block及副本位置,h為主機名 /test/a.log, 3, {blk_1,blk_2}, [{blk_1:[h1,h1,h2]}, {blk_2:[h0,h2,h4]}]
元數據記錄過程:
-
首先記錄在記憶體中,因為記憶體響應速度塊;
-
然後追加到Edit log文件中;
-
定期再將Edit log文件內容,持久化到fsimage磁碟文件中;
CheckPoint:(安全機制的一種考慮)
即:Edit log文件持久化到fsimage中的操作;此動作是在Secondary NameNode中進行的;
Secondary NameNode一般運行在一臺單獨的機器上,因為合併需要大量的CPU和記憶體,並且會一直存儲合併過的命名空間鏡像,以免NN宕機;
-
Edit log文件快滿了,NN通知SN,進行CheckPoint;
-
NN停止寫入Edit log,並生成新的New Edit log文件,來繼續記錄日誌;
-
SN拿到Old Edit log和fsimage副本,併進行合併;
-
合併完成,再上傳給NN,並刪除Old Edit log;
DataNode
即:工作節點;
作用:
-
執行具體的任務:存儲文件塊,被客戶端和NameNode調用;
-
通過心跳(HeartBeat)定時向NameNode發送所存儲的文件的塊信息
工作機制
-
DataNode啟動,對本地磁碟掃描,上報Block信息給NameNode
-
通過心跳機制(heartbeat.interval=3s)與NameNode保持聯繫,心跳的返回帶有NameNode命令信息;
-
如果NameNode 10分鐘(2* heartbeat.recheck.interval)沒有收到DataNode的心跳,則認為lost,複製其Block到其他DataNode
- 參考圖片,看別人博客那裡拿的,後來忘了記下鏈接了,侵刪
數據的完整性
-
創建Block的同時創建checksum,並周期性驗證checksum值;
-
當DataNode讀取Block的時候,會計算checksum值,與創建時的值對比;
-
如果值不一樣,認為Block損壞;會繼續讀取副本Block
目錄結構
DataNode文件不需要格式化;
-
DataNode版本號:./data/tmp/dfs/data/current
[root@hadoop1 current]# cat VERSION #Tue Sep 10 17:51:35 CST 2019 storageID=DS-cc66bc73-0d4d-47a3-8727-69f323c7ae89 # 存儲id clusterID=CID-39e1d84b-8dad-4578-8fdf-f2207368b981 # 集群id,全局唯一 cTime=0 # 記錄創建時間 datanodeUuid=b5c00298-fbc8-4666-8f35-cc27cb7316b1 # 此node唯一標識碼 storageType=DATA_NODE # 存儲類型 layoutVersion=-56 # 版本號
-
數據塊Block版本號:
data/tmp/dfs/data/current/BP-1551134316-192.168.238.129-1568108968205/current
[root@hadoop1 current]# cat VERSION #Tue Sep 10 17:51:35 CST 2019 namespaceID=1573478873 # namenode通過此id區分不同的datanode cTime=0 # blockpoolID=BP-1551134316-192.168.238.129-1568108968205 # 唯一標識一個block pool layoutVersion=-56 # 版本號
在集群中添加新的DataNode
參考:
https://blog.csdn.net/qq_35641192/article/details/80303879
HDFS工作流程
讀寫流程
https://www.cnblogs.com/laowangc/p/8949850.html
下麵提到的FileSystem是DistributedFileSystem的一個實例對象;
讀
-
Client調用FileSystem.open()方法:
FileSystem通過RPC與NN通信,NN返回該文件的部分Block列表(需要的每一個塊在哪個DataNode);
Hadoop會自動算出Client與各個DataNode的距離,選出最短距離的DataNode;
讀取到FSDataInputStream輸入流中,並返回給客戶端;
-
Client調用FSDataInputStream.read()方法:
開始讀取Block,讀取完一個Block,進行checksum驗證,如果出現錯誤,就從下一個有該拷貝的DataNode中讀取;
每讀取一個Block,就關閉此DataNode的輸入流連接,並找到下一個最近的DataNode繼續讀取;
如果Block列表讀完了,總文件還沒有結束,就繼續從NN獲取下一批Block列表,重覆調用read;
-
Client調用FSDataInputStream.close()方法;結束讀取
寫
-
Client調用FileSystem的create()方法:
FileSystem向NN發出請求,在NN的namespace裡面創建一個新的文件,但是並不關聯任何DataNode;
NN檢查文件是否已經存在、操作許可權;如果檢查通過,NN記錄新文件信息,併在某一個DataNode上創建數據塊;
NN返回一個FSDataOutputStream對象,用於Client寫入數據;
-
Client調用輸出流的FSDataOutputStream.write()方法:
開始寫入數據,首先FSDataOutputStream會將數據分割成一個個包,放入數據隊列;
根據NN返回的副本數,以及DataNode列表,先寫入第一個DataNode,此DataNode會推送給下一個DataNode,以此類推,直到副本數創建完畢;(每次都會向隊列返回確認信息)
-
Client調用輸出流的FSDataOutputStream.close()方法:
完成寫入之後,調用close方法,flush數據隊列的數據包,NN返回成功信息;
HDFS基本命令
命令行鍵入:hadoop fs 即可查看命令
1.創建目錄:(/ 為根目錄)
hadoop fs -mkdir /test
hadoop fs -mkdir /test/input (前提test目錄必須存在)
2.查看文件列表:(查看根目錄的文件列表)
hadoop fs -ls /
3.上傳文件到HDFS:
hadoop fs -put /home/whr/a.dat /test/input/a.dat # 複製: hadoop fs -copyFromLocal -f /home/whr/a.dat /test/input/a.dat
4.下載文件到本地:
hadoop fs -get /test/input/a.dat /home/whr/a.dat # 複製: hadoop fs -copyToLocal -f /test/input/a.dat /home/whr/a.dat
5.查看HDFS 文件內容:
hadoop fs -cat /test/input/a.dat
6.刪除HDFS文件:
hadoop fs -rm /test/input/a.dat
7.修改hdfs文件的用戶:用戶組
hadoop fs -chown user_1:group_1 /a.txt
8.查看/test磁碟空間
hadoop fs -df /test
9.刪除全部
hadoop fs -rm -r hdfs://whr-PC:9000/*