隨着數據量愈來愈大,在一個操做系統管轄的範圍內存不下了,那麼就分配到更多的操做系統管理的磁盤中,可是不方便管理和維護,迫切須要一種系統來管理多臺機器上的文件,這就是分佈式文件管理系統。HDFS只是分佈式文件管理系統中的一種。node
HDFS,它是一個文件系統,用於存儲文件,經過目錄樹來定位文件;其次,它是分佈式的,由不少服務器聯合起來實現其功能,集羣中的服務器有各自的角色。linux
HDFS的設計適合一次寫入,屢次讀出的場景,且不支持文件的修改。適合用來作數據分析,並不適合用來作網盤應用。算法
1.3.1 優勢安全
1)高容錯性服務器
(1)數據自動保存多個副本。它經過增長副本的形式,提升容錯性。網絡
(2)某一個副本丟失之後,它能夠自動恢復。架構
2)適合大數據處理併發
(1)數據規模:可以處理數據規模達到 GB、TB、甚至PB級別的數據。app
(2)文件規模:可以處理百萬規模以上的文件數量,數量至關之大。負載均衡
3)流式數據訪問
(1)一次寫入,屢次讀取,不能修改,只能追加。
(2)它能保證數據的一致性。
4)可構建在廉價機器上,經過多副本機制,提升可靠性。
1.3.2 缺點
1)不適合低延時數據訪問,好比毫秒級的存儲數據,是作不到的。
2)沒法高效的對大量小文件進行存儲
(1)存儲大量小文件的話,它會佔用 NameNode大量的內存來存儲文件、目錄和塊信息。這樣是不可取的,由於NameNode的內存老是有限的。
(2)小文件存儲的尋道時間會超過讀取時間,它違反了HDFS的設計目標。
3)併發寫入、文件隨機修改
(1)一個文件只能有一個寫,不容許多個線程同時寫。
(2)僅支持數據 append(追加),不支持文件的隨機修改。
這是和HDFS系統底層設計實現有關係的,HDFS自己的設計就是用來解決海量大文件數據的存儲.,他天生喜歡大數據的處理,大文件存儲在HDFS中,會被切分紅不少的小數據塊,任何一個文件無論有多小,都是一個獨立的數據塊,而這些數據塊的信息則是保存在元數據中的,在以前的博客HDFS基礎裏面介紹過在HDFS集羣的namenode中會存儲元數據的信息,這裏再說一下,元數據的信息主要包括如下3部分:
1)抽象目錄樹
2)文件和數據塊的映射關係,一個數據塊的元數據大小大約是150byte
3)數據塊的多個副本存儲地
而元數據的存儲在磁盤(1和2)和內存中(一、2和3),而服務器中的內存是有上限的,舉個例子:
有100個1M的文件存儲進入HDFS系統,那麼數據塊的個數就是100個,元數據的大小就是100*150byte,消耗了15000byte的內存,可是隻存儲了100M的數據。
有1個100M的文件存儲進入HDFS系統,那麼數據塊的個數就是1個,元數據的大小就是150byte,消耗量150byte的內存,存儲量100M的數據。
因此說HDFS文件系統不適用於存儲小文件。
1)Client:就是客戶端。
(1)文件切分。文件上傳 HDFS 的時候,Client 將文件切分紅一個一個的Block,而後進行存儲。
(2)與NameNode交互,獲取文件的位置信息。
(3)與DataNode交互,讀取或者寫入數據。
(4)Client提供一些命令來管理HDFS,好比啓動或者關閉HDFS。
(5)Client能夠經過一些命令來訪問HDFS。
2)NameNode:就是master,它是一個主管、管理者。
(1)管理HDFS的名稱空間。
(2)管理數據塊(Block)映射信息
(3)配置副本策略
(4)處理客戶端讀寫請求。
3) DataNode:就是Slave。NameNode下達命令,DataNode執行實際的操做。
(1)存儲實際的數據塊。
(2)執行數據塊的讀/寫操做。
4) Secondary NameNode:並不是NameNode的熱備。當NameNode掛掉的時候,它並不能立刻替換NameNode並提供服務。
(1)輔助NameNode,分擔其工做量。
(2)按期合併Fsimage和Edits,並推送給NameNode。
(3)在緊急狀況下,可輔助恢復NameNode。
HDFS中的文件在物理上是分塊存儲(block),塊的大小能夠經過配置參數( dfs.blocksize)來規定,默認大小在hadoop2.x版本中是128M,老版本中是64M。
HDFS的塊比磁盤的塊大,其目的是爲了最小化尋址開銷。若是塊設置得足夠大,從磁盤傳輸數據的時間會明顯大於定位這個塊開始位置所需的時間。於是,傳輸一個由多個塊組成的文件的時間取決於磁盤傳輸速率。
若是尋址時間約爲10ms,而傳輸速率爲100MB/s,爲了使尋址時間僅佔傳輸時間的1%,咱們要將塊大小設置約爲100MB。默認的塊大小128MB。
塊的大小:10ms*100*100M/s = 100M
HDFS做爲一個文件系統。有兩個最主要的功能:上傳和下載。而爲了保障這兩個功能的完美和高效實現,HDFS提供了不少的輔助功能
一、 Hadoop 是 Master/Slave 結構,Master 中有 NameNode 和 ResourceManager,Slave 中有 Datanode 和 NodeManager
二、 Master 啓動的時候會啓動一個 IPC(Inter-Process Comunication,進程間通訊)server 服 務,等待 slave 的連接
三、 Slave 啓動時,會主動連接 master 的 ipc server 服務,而且每隔 3 秒連接一次 master,這 個間隔時間是能夠調整的,參數爲 dfs.heartbeat.interval,這個每隔一段時間去鏈接一次 的機制,咱們形象的稱爲心跳。Slave 經過心跳彙報本身的信息給 master,master 也通 過心跳給 slave 下達命令,
四、 NameNode 經過心跳得知 Datanode 的狀態 ,ResourceManager 經過心跳得知 NodeManager 的狀態
五、 若是 master 長時間都沒有收到 slave 的心跳,就認爲該 slave 掛掉了。
最終NameNode判斷一個DataNode死亡的時間計算公式:
timeout = 10 * 心跳間隔時間 + 2 * 檢查一次消耗的時間
心跳間隔時間:dfs.heartbeat.interval 心跳時間:3s,檢查一次消耗的時間:heartbeat.recheck.interval checktime : 5min,最終宕機以後630s後顯示死亡狀態。
一、HDFS的啓動和關閉都是先啓動NameNode,在啓動DataNode,最後在啓動secondarynamenode。
二、決定HDFS集羣的啓動時長會有兩個因素:
1)磁盤元數據的大小
2)datanode的節點個數
當元數據很大,或者 節點個數不少的時候,那麼HDFS的啓動,須要一段很長的時間,那麼在尚未徹底啓動的時候HDFS可否對外提供服務?
在HDFS的啓動命令start-dfs.sh執行的時候,HDFS會自動進入安全模式
爲了確保用戶的操做是能夠高效的執行成功的,在HDFS發現自身不完整的時候,會進入安全模式。保護本身。
在正常啓動以後,若是HDFS發現全部的數據都是齊全的,那麼HDFS會啓動的退出安全模式
三、對安全模式進行測試
安全模式經常使用操做命令:
hdfs dfsadmin -safemode leave //強制 NameNode 退出安全模式
hdfs dfsadmin -safemode enter //進入安全模式 hdfs dfsadmin -safemode get //查看安全模式狀態 hdfs dfsadmin -safemode wait //等待,一直到安全模式結束
四、安全模式下測試上傳下載,得出結論:
若是一個操做涉及到元數據的修改的話。都不能進行操做,若是一個操做僅僅只是查詢。那是被容許的。所謂安全模式,僅僅只是保護namenode,而不是保護datanode。
第一副本:放置在上傳文件的DataNode上;若是是集羣外提交,則隨機挑選一臺磁盤不太慢、CPU不太忙的節點上;
第二副本:放置在於第一個副本不一樣的機架的節點上;
第三副本:與第二個副本相同機架的不一樣節點上;
若是還有更多的副本:隨機放在節點中;
負載均衡理想狀態:節點均衡、機架均衡和磁盤均衡。
Hadoop的HDFS集羣很是容易出現機器與機器之間磁盤利用率不平衡的狀況,例如:當集羣內新增、刪除節點,或者某個節點機器內硬盤存儲達到飽和值。當數據不平衡時,Map任務可能會分配到沒有存儲數據的機器,這將致使網絡帶寬的消耗,也沒法很好的進行本地計算。
當HDFS負載不均衡時,須要對HDFS進行數據的負載均衡調整,即對各節點機器上數據的存儲分佈進行調整。從而,讓數據均勻的分佈在各個DataNode上,均衡IO性能,防止熱點的發生。進行數據的負載均衡調整,必需要知足以下原則:
數據均衡過程的核心是一個數據均衡算法,該數據均衡算法將不斷迭代數據均衡邏輯,直至集羣內數據均衡爲止。該數據均衡算法每次迭代的邏輯以下:
步驟分析以下:
在第2步中,HDFS會把當前的DataNode節點,根據閾值的設定狀況劃分到Over、Above、Below、Under四個組中。在移動數據塊的時候,Over組、Above組中的塊向Below組、Under組移動。四個組定義以下:
DataNode_usedSpace_percent > Cluster_usedSpace_percent + threshold
Cluster_usedSpace_percent + threshold > DataNode_ usedSpace _percent >Cluster_usedSpace_percent
Cluster_usedSpace_percent > DataNode_ usedSpace_percent > Cluster_ usedSpace_percent – threshold
Cluster_usedSpace_percent – threshold > DataNode_usedSpace_percent
在Hadoop中,包含一個start-balancer.sh腳本,經過運行這個工具,啓動HDFS數據均衡服務。該工具能夠作到熱插拔,即無須重啓計算機和 Hadoop 服務。HadoopHome/bin目錄下的start−balancer.sh腳本就是該任務的啓動腳本。啓動命令爲:‘HadoopHome/bin目錄下的start−balancer.sh腳本就是該任務的啓動腳本。啓動命令爲:‘Hadoop_home/bin/start-balancer.sh –threshold`
影響Balancer的幾個參數:
示例以下:
#啓動數據均衡,默認閾值爲 10% $Hadoop_home/bin/start-balancer.sh #啓動數據均衡,閾值 5% bin/start-balancer.sh –threshold 5 #中止數據均衡 $Hadoop_home/bin/stop-balancer.sh
在hdfs-site.xml文件中能夠設置數據均衡佔用的網絡帶寬限制
<property> <name>dfs.balance.bandwidthPerSec</name> <value>1048576</value> <description> Specifies the maximum bandwidth that each datanode can utilize for the balancing purpose in term of the number of bytes per second. </description> </property>
一、使用 HDFS 提供的客戶端 Client,向遠程的 namenode 發起 RPC 請求
二、namenode 會檢查要建立的文件是否已經存在,建立者是否有權限進行操做,成功則會 爲文件建立一個記錄,不然會讓客戶端拋出異常;
三、當客戶端開始寫入文件的時候,客戶端會將文件切分紅多個 packets,並在內部以數據隊列「data queue(數據隊列)」的形式管理這些 packets,並向 namenode 申請 blocks,獲 取用來存儲 replicas 的合適的 datanode 列表,列表的大小根據 namenode 中 replication 的設定而定;
四、開始以 pipeline(管道)的形式將 packet 寫入全部的 replicas 中。客戶端把 packet 以流的 方式寫入第一個 datanode,該 datanode 把該 packet 存儲以後,再將其傳遞給在此 pipeline 中的下一個 datanode,直到最後一個 datanode,這種寫數據的方式呈流水線的形式。
五、最後一個 datanode 成功存儲以後會返回一個 ack packet(確認隊列),在 pipeline 裏傳遞 至客戶端,在客戶端的開發庫內部維護着"ack queue",成功收到 datanode 返回的 ack packet 後會從"data queue"移除相應的 packet。
六、若是傳輸過程當中,有某個 datanode 出現了故障,那麼當前的 pipeline 會被關閉,出現故 障的 datanode 會從當前的 pipeline 中移除,剩餘的 block 會繼續剩下的 datanode 中繼續 以 pipeline 的形式傳輸,同時 namenode 會分配一個新的 datanode,保持 replicas 設定的 數量。
七、客戶端完成數據的寫入後,會對數據流調用 close()方法,關閉數據流;
八、只要寫入了 dfs.replication.min(最小寫入成功的副本數)的複本數(默認爲 1),寫操做 就會成功,而且這個塊能夠在集羣中異步複製,直到達到其目標複本數(dfs.replication 的默認值爲 3),由於 namenode 已經知道文件由哪些塊組成,因此它在返回成功前只需 要等待數據塊進行最小量的複製。
一、客戶端發起請求:hadoop fs -put hadoop.tar.gz /
客戶端怎麼知道請求發給那個節點的哪一個進程?
由於客戶端會提供一些工具來解析出來你所指定的HDFS集羣的主節點是誰,以及端口號等信息,主要是經過URI來肯定,
url:hdfs://hadoop1:9000
當前請求會包含一個很是重要的信息: 上傳的數據的總大小
二、namenode會響應客戶端的這個請求
namenode的職責:
1 管理元數據(抽象目錄樹結構)
用戶上傳的那個文件在對應的目錄若是存在。那麼HDFS集羣應該做何處理,不會處理
用戶上傳的那個文件要存儲的目錄不存在的話,若是不存在不會建立
二、響應請求
真正的操做:作一系列的校驗,
一、校驗客戶端的請求是否合理
二、校驗客戶端是否有權限進行上傳
三、若是namenode返回給客戶端的結果是 經過, 那就是容許上傳
namenode會給客戶端返回對應的全部的數據塊的多個副本的存放節點列表,如:
file1_blk1 hadoop02,hadoop03,hadoop04
file1_blk2 hadoop03,hadoop04,hadoop05
四、客戶端在獲取到了namenode返回回來的全部數據塊的多個副本的存放地的數據以後,就能夠按照順序逐一進行數據塊的上傳操做
五、對要上傳的數據塊進行邏輯切片
切片分紅兩個階段:
一、規劃怎麼切
二、真正的切物理切片: 1 和 2
邏輯切片: 1
file1_blk1 : file1:0:128
file1_blk2 : file1:128:256
邏輯切片只是規劃了怎麼切
六、開始上傳第一個數據塊
七、客戶端會作一系列準備操做
一、依次發送請求去鏈接對應的datnaode
pipline : client - node1 - node2 - node3
按照一個個的數據包的形式進行發送的。
每次傳輸完一個數據包,每一個副本節點都會進行校驗,依次原路給客戶端
二、在客戶端會啓動一個服務:用戶就是用來等到未來要在這個pipline數據管道上進行傳輸的數據包的校驗信息
客戶端就能知道當前從clinet到寫node1,2,3三個節點上去的數據是否都寫入正確和成功
八、clinet會正式的把這個快中的全部packet都寫入到對應的副本節點
一、block是最大的一個單位,它是最終存儲於DataNode上的數據粒度,由dfs.block.size參數決定,2.x版本默認是128M;注:這個參數由客戶端配置決定;如:System.out.println(conf.get("dfs.blocksize"));//結果是134217728
二、packet是中等的一個單位,它是數據由DFSClient流向DataNode的粒度,以dfs.write.packet.size參數爲參考值,默認是64K;注:這個參數爲參考值,是指真正在進行數據傳輸時,會以它爲基準進行調整,調整的緣由是一個packet有特定的結構,調整的目標是這個packet的大小恰好包含結構中的全部成員,同時也保證寫到DataNode後當前block的大小不超過設定值;
如:System.out.println(conf.get("dfs.write.packet.size"));//結果是65536
三、chunk是最小的一個單位,它是DFSClient到DataNode數據傳輸中進行數據校驗的粒度,由io.bytes.per.checksum參數決定,默認是512B;注:事實上一個chunk還包含4B的校驗值,於是chunk寫入packet時是516B;數據與檢驗值的比值爲128:1,因此對於一個128M的block會有一個1M的校驗文件與之對應;
如:System.out.println(conf.get("io.bytes.per.checksum"));//結果是512
九、clinet進行校驗,若是校驗經過,表示該數據塊寫入成功
十、重複7 8 9 三個操做,來繼續上傳其餘的數據塊
十一、客戶端在乎識到全部的數據塊都寫入成功以後,會給namenode發送一個反饋,就是告訴namenode當前客戶端上傳的數據已經成功。
一、客戶端調用FileSystem 實例的open 方法,得到這個文件對應的輸入流InputStream。
二、經過RPC 遠程調用NameNode ,得到NameNode 中此文件對應的數據塊保存位置,包括這個文件的副本的保存位置( 主要是各DataNode的地址) 。
三、得到輸入流以後,客戶端調用read 方法讀取數據。選擇最近的DataNode 創建鏈接並讀取數據。
四、若是客戶端和其中一個DataNode 位於同一機器(好比MapReduce 過程當中的mapper 和reducer),那麼就會直接從本地讀取數據。
五、到達數據塊末端,關閉與這個DataNode 的鏈接,而後從新查找下一個數據塊。
六、不斷執行第2 - 5 步直到數據所有讀完。
七、客戶端調用close ,關閉輸入流DF S InputStream。
bin/hadoop fs 具體命令
[root@node21 hadoop-2.7.6]$ bin/hadoop fs
[-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 ...]]
(1)-help:輸出這個命令參數(2)-ls: 顯示目錄信息(3)-mkdir:在hdfs上建立目錄(4)-moveFromLocal從本地剪切粘貼到hdfs(5)-appendToFile :追加一個文件到已經存在的文件末尾(6)-cat :顯示文件內容(7)-tail:顯示一個文件的末尾(8)-chgrp 、-chmod、-chown:linux文件系統中的用法同樣,修改文件所屬權限(9)-copyFromLocal:從本地文件系統中拷貝文件到hdfs路徑去(10)-copyToLocal:從hdfs拷貝到本地t(11)-cp :從hdfs的一個路徑拷貝到hdfs的另外一個路徑(12)-mv:在hdfs目錄中移動文件(13)-get:等同於copyToLocal,就是從hdfs下載文件到本地(14)-getmerge :合併下載多個文件,好比hdfs的目錄 /aaa/下有多個文件:log.1, log.2,log.3,...(15)-put:等同於copyFromLocal(16)-rm:刪除文件或文件夾(17)-rmdir:刪除空目錄(18)-df :統計文件系統的可用空間信息(19)-du統計文件夾的大小信息(20)-setrep:設置hdfs中文件的副本數量