文章目錄
一.分佈式文件系統HDFS
隨着數據量越來越大,在一個操作系統存不下所有的數據,那麼就分配到更多的操作系統管理的磁盤中,但是不方便管理和維護,迫切需要一種系統來管理多臺機器上的文件,這就是分佈式文件管理系統。
HDFS全稱是Hadoop Distributed File System,它是一個分佈式文件系統,用於存儲文件,通過目錄樹來定位文件,由很多服務器聯合起來實現其功能,集羣中的服務器有各自的角色,如NameNode、DataNode,各種角色有各自的功能。HDFS適合一次寫入,多次讀出的場景,且不支持文件的修改。適合用來做數據分析,並不適合用來做網盤應用。
二.HDFS的特點及適用場景
2.1 HDFS的高容錯性
數據自動保存多個副本。HDFS通過增加副本的形式,提高容錯性,某一個副本丟失以後,可以自動恢復。HDFS可構建在廉價機器上,通過多副本機制,提高可靠性。
2.2 HDFS的適用場景
HDFS適合處理文件數量非常多,單個文件比較大的數據。HDFS能夠處理規模達到GB、TB、甚至PB級別的數據。
也有很多不適合HDFS使用的場合,比如低延時數據訪問,毫秒級的存儲數據,HDFS是做不到的。如果數據是由大量小文件組成的,那麼HDFS也不適用,這是因爲HDFS架構的問題,存儲大量小文件會佔用NameNode大量的內存來存儲文件目錄和塊信息。這樣是不可取的,因爲NameNode的內存總是有限的;同時小文件存儲的尋址時間會超過讀取時間,它違反了HDFS的設計目標。除此之外,HDFS還不支持併發寫入、文件隨機修改。使用HDFS時,一個文件只能有一個寫,不允許多個線程同時寫;HDFS僅支持數據append(追加),不支持文件的隨機修改。
三.HDFS架構
3.1 HDFS集羣中的主要角色
HDFS集羣中各主機的角色主要有NameNode(nn)和DataNode(dn),Client,和SecondNameNode(2nn)。
NameNode是Master,它是集羣的管理者。負責管理HDFS的名稱空間、配置副本策略和數據塊(Block)映射信息,同時還可以處理客戶端讀寫請求。
DataNode是Slave,NameNode下達命令,DataNode執行實際的操作。DataNode主要負責存儲實際的數據塊和執行數據塊的讀/寫操作。
Client負責與用戶交互,同時它還有其他功能,1.文件切分,文件上傳HDFS的時候,Client將文件切分成一個一個的Block,然後進行上傳;2.與NameNode交互,獲取文件的位置信息;3.與DataNode交互,讀取或者寫入數據;4.提供一些命令來管理HDFS,比如NameNode格式化;4.可以通過Client使用一些命令來訪問HDFS,比如對HDFS增刪查改操作;
SecondaryNameNode負責輔助NameNode,分擔其工作量,比如定期合併Fsimage和Edits,並推送給NameNode ;在緊急情況下,可輔助恢復NameNode。
3.2 NameNode和Secondary Namenode的工作原理
FsImage和Edits
在HDFS集羣中,元數據放在內存中,在磁盤中備份元數據的FsImage,防止因爲斷電,造成元數據丟失。當在內存中的元數據更新時,同時更新FsImage的效率非常低,所以HDFS引入Edits文件(只進行追加操作,效率很高)。每當元數據有更新或者添加元數據時,修改內存中的元數據並追加到Edits中。這樣,一旦NameNode節點斷電,可以通過FsImage和Edits的合併,恢復元數據。
爲了避免長時間添加數據到Edits中,導致文件數據過大,效率降低的問題,HDFS會定期進行FsImage和Edits的合併,合併操作由NameNode完成,由於NameNode還有其他的任務,比如指揮DataNode工作等,這會使NameNode的壓力倍增,所以HDFS引入了Secondary Namenode這一角色,專門負責FsImage和Edits的合併。
NameNode和Secondary Namenode的工作流程
第一階段: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。
NameNode和Secondary Namenode功能詳解
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中。
3.3 DataNode的工作原理
- 一個數據塊在DataNode上以文件形式存儲在磁盤上,包括兩個文件,一個是數據本身,一個是元數據包括數據塊的長度,塊數據的校驗和,以及時間戳。
- DataNode啓動後向NameNode註冊,通過後,週期性(1小時)的向NameNode上報所有的塊信息。
- 心跳是每3秒一次,心跳返回結果帶有NameNode給該DataNode的命令如複製塊數據到另一臺機器,或刪除某個數據塊。如果超過10分鐘沒有收到某個DataNode的心跳,則認爲該節點不可用。
- 集羣運行中可以安全加入和退出一些機器。
四.HDFS讀寫數據
4.1 HDFS寫數據流程
- 客戶端通過DistributedFileSystem模塊向NameNode請求上傳文件,NameNode檢查目標文件是否已存在,父目錄是否存在。
- NameNode返回是否可以上傳。
- 客戶端請求第一個 Block上傳到哪幾個DataNode服務器上。
- NameNode返回3個DataNode節點,分別爲dn1、dn2、dn3。
- 客戶端通過FSDataOutputStream模塊請求dn1上傳數據,dn1收到請求會繼續調用dn2,然後dn2調用dn3,將這個通信管道建立完成。
- dn1、dn2、dn3逐級應答客戶端。
- 客戶端開始往dn1上傳第一個Block(先從磁盤讀取數據放到一個本地內存緩存),以Packet爲單位,dn1收到一個Packet就會傳給dn2,dn2傳給dn3;dn1每傳一個packet會放入一個應答隊列等待應答。
- 當一個Block傳輸完成之後,客戶端再次請求NameNode上傳第二個Block的服務器。(重複執行3-7步)。
NameNode選擇接收數據的DataNode的規則
在HDFS寫數據的過程中,NameNode會選擇距離待上傳數據最近距離(拓撲距離)的DataNode接收數據,同時NameNode還需要根據一定的規則選擇DataNode存儲數據的
拓撲距離計算
拓撲距離的計算可以參考下圖中給出的例子:
節點/d1/r1/n-0到節點/d1/r1/n-0的拓撲距離爲0(同一節點上的進程)
節點/d1/r1/n-1到節點/d1/r1/n-2的拓撲距離爲2(同一機架上的不同節點)
節點/d1/r2/n-0到節點/d1/r3/n-2的拓撲距離爲4(同一數據中心不同機架上的節點)
節點/d1/r2/n-1到節點/d2/r4/n-1的拓撲距離爲6(不同數據中心的節點)
NameNode選擇副本節點
HDFS集羣默認會存儲數據的三個副本,副本的存儲位置選擇遵循以下規則:
第一個副本在Client所處的節點上。如果客戶端在集羣外,隨機選一個。
第二個副本和第一個副本位於相同機架,隨機節點。
第三個副本位於不同機架,隨機節點。
4.2 HDFS讀數據流程
- 客戶端通過DistributedFileSystem向NameNode請求下載文件,NameNode通過查詢元數據,找到文件塊所在的DataNode地址。
- 挑選一臺DataNode(就近原則,然後隨機)服務器,請求讀取數據。
- DataNode開始傳輸數據給客戶端(從磁盤裏面讀取數據輸入流,以Packet爲單位來做校驗)。
- 客戶端以Packet爲單位接收,先在本地緩存,然後寫入目標文件。
五.使用shell命令操作HDFS
HDFS的使用比較簡單,使用過程中經常在shell中使用hadoop命令操作HDFS,輸入hadoop -help
命令,可以看到hadoop命令支持的所有參數。
[-appendToFile <localsrc> ... <dst>]
[-cat [-ignoreCrc] <src> ...]
[-checksum <src> ...]
[-chgrp [-R] GROUP PATH...]
[-chmod [-R] <MODE[,MODE]... | OCTALMODE> PATH...]
[-chown [-R] [OWNER][:[GROUP]] PATH...]
[-copyFromLocal [-f] [-p] <localsrc> ... <dst>]
[-copyToLocal [-p] [-ignoreCrc] [-crc] <src> ... <localdst>]
[-count [-q] <path> ...]
[-cp [-f] [-p] <src> ... <dst>]
[-createSnapshot <snapshotDir> [<snapshotName>]]
[-deleteSnapshot <snapshotDir> <snapshotName>]
[-df [-h] [<path> ...]]
[-du [-s] [-h] <path> ...]
[-expunge]
[-get [-p] [-ignoreCrc] [-crc] <src> ... <localdst>]
[-getfacl [-R] <path>]
[-getmerge [-nl] <src> <localdst>]
[-help [cmd ...]]
[-ls [-d] [-h] [-R] [<path> ...]]
[-mkdir [-p] <path> ...]
[-moveFromLocal <localsrc> ... <dst>]
[-moveToLocal <src> <localdst>]
[-mv <src> ... <dst>]
[-put [-f] [-p] <localsrc> ... <dst>]
[-renameSnapshot <snapshotDir> <oldName> <newName>]
[-rm [-f] [-r|-R] [-skipTrash] <src> ...]
[-rmdir [--ignore-fail-on-non-empty] <dir> ...]
[-setfacl [-R] [{-b|-k} {-m|-x <acl_spec>} <path>]|[--set <acl_spec> <path>]]
[-setrep [-R] [-w] <rep> <path> ...]
[-stat [format] <path> ...]
[-tail [-f] <file>]
[-test -[defsz] <path>]
[-text [-ignoreCrc] <src> ...]
[-touchz <path> ...]
[-usage [cmd ...]]
-help
功能:輸出這個命令參數手冊
-ls
功能:顯示目錄信息
示例: hadoop fs -ls hdfs://hadoop-server01:9000/
-mkdir
功能:在hdfs上創建目錄
示例:hadoop fs -mkdir -p /aaa/bbb/cc/dd
-moveFromLocal
功能:從本地剪切粘貼到hdfs
示例:hadoop fs - moveFromLocal /home/hadoop/a.txt /aaa/bbb/cc/dd
-moveToLocal
功能:從hdfs剪切粘貼到本地
示例:hadoop fs - moveToLocal /aaa/bbb/cc/dd /home/hadoop/a.txt
–appendToFile
功能:追加一個文件到已經存在的文件末尾
示例:hadoop fs -appendToFile ./hello.txt hdfs://hadoop-server01:9000/hello.txt
可以簡寫爲:
Hadoop fs -appendToFile ./hello.txt /hello.txt
-cat
功能:顯示文件內容
示例:hadoop fs -cat /hello.txt
-tail
功能:顯示一個文件的末尾
示例:hadoop fs -tail /weblog/access_log.1
-text
功能:以字符形式打印一個文件的內容
示例:hadoop fs -text /weblog/access_log.1
-chgrp
-chmod
-chown
功能:linux文件系統中的用法一樣,對文件所屬權限
示例:
hadoop fs -chmod 666 /hello.txt
hadoop fs -chown someuser:somegrp /hello.txt
-copyFromLocal
功能:從本地文件系統中拷貝文件到hdfs路徑去
示例:hadoop fs -copyFromLocal ./jdk.tar.gz /aaa/
-copyToLocal
功能:從hdfs拷貝到本地
示例:hadoop fs -copyToLocal /aaa/jdk.tar.gz
-cp
功能:從hdfs的一個路徑拷貝hdfs的另一個路徑
示例: hadoop fs -cp /aaa/jdk.tar.gz /bbb/jdk.tar.gz.2
-mv
功能:在hdfs目錄中移動文件
示例: hadoop fs -mv /aaa/jdk.tar.gz /
-get
功能:等同於copyToLocal,就是從hdfs下載文件到本地
示例:hadoop fs -get /aaa/jdk.tar.gz
-getmerge
功能:合併下載多個文件
示例:比如hdfs的目錄 /aaa/下有多個文件:log.1, log.2,log.3,…
hadoop fs -getmerge /aaa/log.* ./log.sum
-put
功能:等同於copyFromLocal
示例:hadoop fs -put /aaa/jdk.tar.gz /bbb/jdk.tar.gz.2
-rm
功能:刪除文件或文件夾
示例:hadoop fs -rm -r /aaa/bbb/
-rmdir
功能:刪除空目錄
示例:hadoop fs -rmdir /aaa/bbb/ccc
-df
功能:統計文件系統的可用空間信息
示例:hadoop fs -df -h /
-du
功能:統計文件夾的大小信息
示例:
hadoop fs -du -s -h /aaa/*
-count
功能:統計一個指定目錄下的文件節點數量
示例:hadoop fs -count /aaa/
-setrep
功能:設置hdfs中文件的副本數量
示例:hadoop fs -setrep 3 /aaa/jdk.tar.gz
這裏設置的副本數只是記錄在namenode的元數據中,是否真的會有這麼多副本,還得看datanode的數量