Hadoop分佈式文件系統(HDFS)是一種分佈式文件系統,用於在普通商用硬件上運行。它與現有的分佈式文件系統有許多類似之處。然而,與其餘分佈式文件系統的區別很大。HDFS具備高度的容錯能力,旨在部署在低成本的硬件上。HDFS提供對應用程序數據的高吞吐量訪問,適用於具備大數據集的應用程序。HDFS放寬了一些POSIX要求,以便對文件系統數據進行流式訪問。HDFS最初是做爲Apache Nutch Web搜索引擎項目的基礎架構構建的。HDFS是Apache Hadoop Core項目的一部分。http://hadoop.apache.org/html
硬件故障很常見而不例外。HDFS實例能夠由數百或數千臺服務器機器組成,每臺服務器存儲部分文件系統的數據。事實上,有大量的組件,而且每一個組件具備不必定的故障機率,這意味着HDFS的某些組件老是不起做用的。所以,故障檢測和快速自動恢復是HDFS的核心架構。node
在HDFS上運行的應用程序須要對其數據集進行流式訪問。HDFS不是用於提供普通應用訪問的文件系統。HDFS的設計更多用於批量處理,而不是用戶的交互式使用。重點是數據訪問的高吞吐量,而不是數據訪問的低延遲。POSIX施加了許多難於爲HDFS定位的應用程序所需的硬要求。POSIX語義在幾個關鍵領域已被交易,以提升數據吞吐率。shell
在HDFS上運行的應用程序具備較大的數據集。HDFS中的典型文件大小爲千兆字節。所以,HDFS被調整爲支持大文件。它應該提供高聚合數據帶寬並擴展到單個集羣中的數百個節點。它應該在一個實例中支持數千萬個文件。apache
HDFS數據訪問模式爲一次寫入屢次讀取。文件一旦建立、寫入和關閉後,除了追加和截斷,文件內容再也不變化。將內容附加到文件的末尾是受支持的,但不能隨意更新。該假設簡化了數據一致性問題,並實現了高吞吐量數據訪問。MapReduce應用程序或Web爬蟲程序應用程序與此模型完美匹配。api
若是應用程序可以很近德運行在其須要的數據,則應用程序所請求的計算效率更高【應用處理本機數據比遠程數據更快】。當數據集很大時,這一點尤爲如此。這樣能夠最大限度地減小網絡擁塞並提升系統的總體吞吐量。假設一般更好地將計算遷移到更接近數據位置的位置,而不是將數據移動到應用程序運行的位置。HDFS爲應用程序提供接口,使其更接近數據所在的位置。瀏覽器
HDFS被設計爲能夠從一個平臺輕鬆地移植到另外一個平臺。這有助於HDFS做爲大型應用程序的首選平臺。緩存
HDFS具備主/從結構。HDFS集羣包含單一的NameNode做爲master服務器,用於管理文件系統命名空間,並調節客戶端對文件的訪問。此外,還有一些DataNodes,一般是集羣中每一個節點的一個,它們管理鏈接到運行的節點的存儲。HDFS公開了文件系統命名空間,並容許將用戶數據存儲在文件中。在內部,文件被分割成一個或多個塊,而且這些塊被存儲在一組DataNodes中。NameNode執行文件系統命名空間操做,如打開,關閉和重命名文件和目錄。它還肯定塊到DataNodes的映射。DataNodes負責從文件系統的客戶端提供讀取和寫入請求。DataNode還能夠根據NameNode的指示執行塊建立,刪除和複製。安全
NameNode和DataNode是用於在商用機上運行的軟件。這些機器一般運行GNU / Linux操做系統(OS)。HDFS使用Java語言構建;任何支持Java的機器均可以運行NameNode或DataNode軟件。高度可移植的Java語言的使用意味着HDFS能夠部署在普遍的機器上。典型的部署具備僅運行NameNode軟件的專用機器。集羣中的每一個其餘計算機都運行DataNode軟件的一個實例。該架構並不排除在同一臺機器上運行多個DataNodes,而是在不多出現的實際部署中。bash
集羣中單個NameNode的存在大大簡化了系統的體系結構。NameNode是全部HDFS元數據的仲裁器和存儲庫。該系統的設計方式使得用戶數據不會流經NameNode。服務器
HDFS支持傳統的分層文件組織。用戶或應用程序能夠建立目錄並將文件存儲在這些目錄中。文件系統命名空間層次結構與大多數其餘現有文件系統相似;能夠建立和刪除文件,將文件從一個目錄移動到另外一個目錄,或者重命名文件。HDFS支持用戶配額和訪問權限。HDFS不支持硬連接或軟連接。然而,HDFS架構並不排除實現這些功能。
NameNode維護文件系統命名空間。文件系統名稱空間或其屬性的任何更改都由NameNode記錄。應用程序能夠指定應由HDFS維護的文件的副本數。文件的副本數稱爲該文件的複製因子。該信息由NameNode存儲。
HDFS設計用於在大型集羣中的機器之間可靠地存儲很是大的文件。它將每一個文件存儲爲一系列塊。複製文件的塊以進行容錯。塊大小和複製因子是可配置的每一個文件。【hdfs-site.xml dfs.block.size dfs.replication】
除了最後一個塊以外的文件中的全部塊都是相同的大小,而用戶能夠在將可變長度塊的支持添加到追加和hsync以後啓動一個新的塊,而不會將最後一個塊填充到配置的塊大小。
應用程序能夠指定文件的副本數。能夠在文件建立時指定複製因子,稍後更改。HDFS中的文件是一次寫入(除了附加和截斷以外),而且在任什麼時候候都有一個做者。
NameNode作出關於塊複製的全部決定。它週期性地從集羣中的每一個DataNode接收到一個心跳和一個阻塞報告。收到心跳意味着DataNode正常運行。Blockreport包含DataNode上全部塊的列表。
複製品的放置對於HDFS的可靠性和性能相當重要。優化複製放置將HDFS與大多數其餘分佈式文件系統區分開來。這是一個須要大量調整和體驗的功能。機架感知複製放置策略的目的是提升數據可靠性,可用性和網絡帶寬利用率。目前的複製放置政策的實施是朝這個方向努力的第一步。實施這一政策的短時間目標是在生產系統上進行驗證,更多地瞭解其行爲,併爲更復雜的政策進行測試和研究奠基基礎。
大型HDFS實例在一般分佈在多個機架上的計算機集羣上運行。不一樣機架中的兩個節點之間的通訊必須通過交換機。在大多數狀況下,同一機架中的機器之間的網絡帶寬大於不一樣機架中的機器之間的網絡帶寬。
NameNode經過Hadoop機架意識【http://hadoop.apache.org/docs/current/hadoop-project-dist/hadoop-common/RackAwareness.html】中概述的過程來肯定每一個DataNode所屬的機架ID。一個簡單但不是最優的策略是將副本放在獨特的機架上。這能夠防止整個機架發生故障時丟失數據,並容許在讀取數據時使用多個機架的帶寬。該策略在集羣中均勻分配副本,這使得輕鬆平衡組件故障時的負載。可是,這種策略會增長寫入的成本,由於寫入須要將塊傳輸到多個機架。
對於常見狀況,當複製因子爲3時,HDFS的放置策略是將一個副本放在本地機架中的一個節點上,另外一個在本地機架上的另外一個節點上,最後在不一樣機架中的不一樣節點上。該策略能夠減小機架間的寫入流量,這一般會提升寫入性能。機架故障的機會遠小於節點故障的機會;此政策不影響數據的可靠性和可用性保證。然而,它確實減小了在讀取數據時使用的整體網絡帶寬,由於塊僅放置在兩個獨特的機架中,而不是三個。使用此策略,文件的副本不會均勻分佈在機架中。三分之一的副本在一個節點上,三分之二的副本在一個機架上,另外三個是均勻分佈在剩餘的機架上。此策略可改善寫入性能,而不會影響數據的可靠性或讀取性能。
若是複製因子大於3,則隨機肯定第4個和之後副本的位置,同時保持每一個機架的副本數量低於上限(基本爲(複製1)/機架2))。
因爲NameNode不容許DataNodes具備相同塊的多個副本,因此建立的副本的最大數目是當時的DataNodes的總數。
在將存儲類型和存儲策略【http://hadoop.apache.org/docs/current/hadoop-project-dist/hadoop-hdfs/ArchivalStorage.html】的支持添加到HDFS以後,除了上述的機架感知以外,NameNode還會將策略考慮在副本位置。NameNode首先根據機架識別選擇節點,而後檢查候選節點是否具備與文件關聯的策略所需的存儲。若是候選節點沒有存儲類型,則NameNode將查找另外一個節點。若是在第一個路徑中找不到足夠的放置副本的節點,則NameNode將在第二個路徑中查找具備備用存儲類型的節點。
此處描述的當前,默認的複製放置策略是一項正在進行的工做。
爲了最大限度地減小全局帶寬消耗和讀取延遲,HDFS會嘗試從最接近讀卡器的副本獲取讀取請求。若是在與讀取器節點相同的機架上存在副本,則該副本優選知足讀取請求。若是HDFS羣集跨越多個數據中心,則駐留在本地數據中心的副本優先於任何遠程副本。
在啓動時,NameNode進入一個稱爲Safemode的特殊狀態。NameNode處於Safemode狀態時,不會複製數據塊。NameNode從DataNodes接收心跳和Blockreport消息。Blockreport包含DataNode承載的數據塊列表。每一個塊具備指定的最小數量的副本。當使用NameNode檢入數據塊的最小副本數時,塊被認爲是安全複製的。在可配置百分比的安全複製數據塊使用NameNode(加上另外30秒)以後,NameNode退出Safemode狀態。而後,它肯定仍然具備少於指定數量的副本的數據塊(若是有)的列表。NameNode而後將這些塊複製到其餘DataNodes。
1.EditLog
2.FsImage
HDFS命名空間由NameNode存儲。NameNode使用名爲EditLog的事務日誌持續記錄文件系統元數據發生的每一個更改。例如,在HDFS中建立一個新文件會致使NameNode將一個記錄插入到EditLog中。相似地,更改文件的複製因子將致使將新記錄插入到EditLog中。NameNode使用其本地主機OS文件系統中的文件來存儲EditLog。整個文件系統命名空間(包括將塊映射到文件和文件系統屬性)存儲在一個名爲FsImage的文件中。FsImage做爲文件存儲在NameNode的本地文件系統中。
checkpoint 用於合併EditLog至FsImage,FsImage是文件系統最新的元數據,但不直接更新FsImage,而是定時合併EditLog至FsImage
NameNode將整個文件系統命名空間和文件Blockmap的映像保存在內存中。當NameNode啓動或檢查點由可配置的閾值觸發時,它從磁盤讀取FsImage和EditLog,將全部來自EditLog的事務應用到FsImage的內存中表示,並將該新版本刷新爲保存到硬盤做爲新的FsImage。它能夠截斷舊的EditLog,由於它的事務已被應用到永久的FsImage。這個過程稱爲檢查點。檢查點的目的是經過拍攝文件系統元數據的快照並將其保存到FsImage來確保HDFS具備文件系統元數據的一致視圖。即便閱讀FsImage也是有效的,直接對FsImage進行增量編輯是不正確的。咱們不用修改每一個編輯的FsImage,而是在Editlog中保持編輯。在檢查點期間,Editlog中的更改應用於FsImage。能夠在給定的時間間隔(dfs.namenode.checkpoint.period)上以秒爲單位觸發檢查點,或在給定數量的文件系統事務已累積(dfs.namenode.checkpoint.txns)後觸發。若是這兩個屬性都被設置,則要達到的第一個閾值觸發一個檢查點。
DataNode將HDFS數據存儲在本地文件系統中的文件中。DataNode不瞭解HDFS文件。它將HDFS數據的每一個塊存儲在其本地文件系統中的單獨文件中。DataNode不會在同一目錄中建立全部文件。相反,它使用啓發式方法來肯定每一個目錄的最佳文件數,並適當地建立子目錄。在同一目錄中建立全部本地文件並非最佳的,由於本地文件系統可能沒法在單個目錄中有效地支持大量文件。當DataNode啓動時,它將掃描其本地文件系統,生成與每一個這些本地文件對應的全部HDFS數據塊的列表,並將此報告發送到NameNode。該報告稱爲Blockreport。
全部HDFS通訊協議分層在TCP / IP協議之上。客戶端與NameNode機器上配置TCP端口創建鏈接。利用ClientProtocol協議與NameNode進行通訊。DataNode使用DataNode協議與NameNode進行通訊。遠程過程調用(RPC)抽象包含客戶端協議和數據節點協議。按照設計,NameNode從不啓動任何RPC。相反,它只響應DataNodes或客戶端發出的RPC請求。
HDFS的主要目標是即便存在故障也可以可靠地存儲數據。三種常見的故障類型是NameNode故障,DataNode故障和網絡分區
每一個DataNode按期向NameNode發送一個心跳信息。網絡分區可能致使DataNodes的一個子集與NameNode失去鏈接。NameNode經過不存在心跳消息來檢測此狀況。NameNode將DataNodes標記爲沒有最近的Heartbeats死機,而且不會向其轉發任何新的IO請求。任何已註冊到死亡數據節點的數據再也不適用於HDFS。DataNode死亡可能致使某些程序段的複製因子低於其指定值。NameNode不斷跟蹤哪些塊須要複製,並在必要時啓動複製。重複複製的必要性可能因爲許多緣由:DataNode可能變得不可用,副本可能會損壞,DataNode上的硬盤可能會失敗,或者可能會增長文件的複製因素。
標記DataNodes死機的超時保守長(默認爲10分鐘以上),以免DataNodes的狀態拍攝引發的複製風暴。用戶能夠設置更短的間隔,將DataNodes標記爲過期,並經過配置讀取和/或寫入性能敏感工做負載來避免過期的節點。
HDFS架構與數據從新平衡方案兼容。若是DataNode上的可用空間低於某個閾值,則方案可能會自動將數據從一個DataNode移動到另外一個DataNode。在特定文件需求忽然增長的狀況下,方案可能會動態建立其餘副本並從新平衡羣集中的其餘數據。這些類型的數據從新平衡計劃還沒有實施。
從DataNode獲取的數據塊可能會被破壞。這多是因爲存儲設備故障,網絡故障或錯誤的軟件而致使的。HDFS客戶端軟件對HDFS文件的內容執行校驗和檢查。當客戶端建立一個HDFS文件時,它計算文件的每一個塊的校驗和,並將這些校驗和存儲在同一HDFS命名空間中的單獨的隱藏文件中。當客戶端檢索文件內容時,它會驗證其從每一個DataNode接收到的數據與存儲在相關校驗和文件中的校驗和相匹配。若是沒有,則客戶端能夠選擇從另外一個具備該塊副本的DataNode中檢索該塊。
FsImage和EditLog是HDFS的中心數據結構。這些文件的損壞可能致使HDFS實例不起做用。所以,NameNode能夠配置爲支持維護FsImage和EditLog的多個副本。對FsImage或EditLog的任何更新都會致使FsImages和EditLogs中的每個被同步更新。FsImage和EditLog的多個副本的此同步更新可能下降NameNode能夠支持的每秒命名空間事務的速率。然而,這種降級是能夠接受的,由於即便HDFS應用程序本質上是很是數據密集的,它們也不是元數據密集型的。當NameNode從新啓動時,它會選擇最新一致的FsImage和EditLog來使用。
快照支持在特定時刻存儲數據副本。快照功能的一個用法多是將損壞的HDFS實例回滾到先前已知的好時間點。
HDFS旨在支持很是大的文件。與HDFS兼容的應用程序是處理大型數據集的應用程序。這些應用程序只寫一次數據,但它們讀取一次或屢次,並要求這些讀取在流速下知足。HDFS支持對文件的一次讀取多語義。HDFS使用的典型塊大小是128 MB。所以,將HDFS文件切成128 MB塊,若是可能,每一個塊將駐留在不一樣的DataNode上。
建立文件的客戶端請求不會當即到達NameNode。實際上,最初,HDFS客戶端將文件數據緩存到本地緩衝區中。應用程序寫入被透明地重定向到本地緩衝區。當本地文件累積超過一個塊大小的數據時,客戶端將鏈接NameNode。NameNode將文件名插入到文件系統層次結構中,爲其分配一個數據塊。NameNode使用DataNode和目標數據塊的標識響應客戶端請求。而後客戶端將數據塊從本地緩衝區刷新到指定的DataNode。關閉文件時,本地緩衝區中剩餘的未刷新數據將傳輸到DataNode。客戶端而後告訴NameNode該文件是關閉的。此時,NameNode將文件建立操做提交到持久存儲。若是NameNode在文件關閉以前死機,該文件將丟失。
上述方法在仔細考慮了在HDFS上運行的目標應用程序後才採用。這些應用程序須要流式寫入文件。若是客戶端直接寫入遠程文件而沒有任何客戶端緩衝,網絡速度和網絡擁塞就會大大影響吞吐量。這種作法並不是沒有先例。早期的分佈式文件系統,例如AFS使用客戶端緩存來提升性能。POSIX要求已放寬,以實現更高性能的數據上傳。
當客戶端將數據寫入HDFS文件時,首先將其數據寫入本地緩衝區,如上一節所述。假設HDFS文件的複製因子爲3。當本地緩衝區累積一大批用戶數據時,客戶端將從NameNode中檢索一個DataNodes列表。該列表包含將承載該塊的副本的DataNodes。而後,客戶端將數據塊刷新到第一個DataNode。第一個DataNode開始以小部分接收數據,將每一個部分寫入其本地存儲庫,並將該部分傳輸到列表中的第二個DataNode。第二個DataNode又開始接收數據塊的每一個部分,將該部分寫入其存儲庫,而後將該部分刷新到第三個DataNode。最後,第三個DataNode將數據寫入本地存儲庫。所以,DataNode能夠在流水線中接收來自前一個數據的數據,而且同時將數據轉發到流水線中的下一個數據。所以,數據從一個DataNode流水線到下一個。
HDFS能夠從應用程序以許多不一樣的方式訪問。原本,HDFS提供了一個FileSystem Java API,供應用程序使用。此Java API和REST API的C語言包裝器也可用。另外,HTTP瀏覽器還能夠用來瀏覽HDFS實例的文件。經過使用NFS網關,HDFS能夠做爲客戶端本地文件系統的一部分進行安裝。
HDFS容許以文件和目錄的形式組織用戶數據。它提供了一個名爲FS shell的命令行接口,可以讓用戶與HDFS中的數據進行交互。該命令集的語法相似於用戶已經熟悉的其餘shell(例如bash,csh)。如下是一些示例操做/命令對:
Action | Command |
---|---|
Create a directory named /foodir | bin/hadoop dfs -mkdir /foodir |
Remove a directory named /foodir | bin/hadoop fs -rm -R /foodir |
View the contents of a file named /foodir/myfile.txt | bin/hadoop dfs -cat /foodir/myfile.txt |
FS shell針對須要使用腳本語言與存儲數據進行交互的應用程序。
DFSAdmin命令集用於管理HDFS集羣。這些是僅由HDFS管理員使用的命令。如下是一些示例操做/命令對:
Action | Command |
---|---|
Put the cluster in Safemode | bin/hdfs dfsadmin -safemode enter |
Generate a list of DataNodes | bin/hdfs dfsadmin -report |
Recommission or decommission DataNode(s) | bin/hdfs dfsadmin -refreshNodes |
典型的HDFS安裝配置Web服務器以經過可配置的TCP端口公開HDFS命名空間。這容許用戶瀏覽HDFS命名空間,並使用Web瀏覽器查看其文件的內容。
若是啓用垃圾箱配置,FS Shell刪除的文件不會當即從HDFS中刪除。相反,HDFS將其移動到垃圾目錄(每一個用戶在/user/<username>/.Trash下都有本身的垃圾文件目錄)。只要文件保留在垃圾箱中,文件能夠快速恢復。
大多數最近刪除的文件被移動到當前垃圾桶目錄(/user/<username>/.Trash/Current),而且在可配置的時間間隔內,HDFS建立檢查點(在/ user / <username> /。垃圾桶/ <date>下)對於當前垃圾目錄中的文件,並在舊的檢查點過時時刪除它們。請參閱FS shell關於檢查垃圾的清除命令。
Trash生命週期到期時,Namenode從HDFS命名空間中刪除該文件。刪除文件會致使與文件關聯的塊被釋放。請注意,在用戶刪除文件的時間與HDFS中可用空間相應增長的時間之間可能會有明顯的時間延遲。
如下是一個示例,顯示如何從FS Shell從HDFS中刪除文件。咱們建立了2個文件(test1&test2)
$ hadoop fs -mkdir -p delete/test1 $ hadoop fs -mkdir -p delete/test2 $ hadoop fs -ls delete/ Found 2 items drwxr-xr-x - hadoop hadoop 0 2015-05-08 12:39 delete/test1 drwxr-xr-x - hadoop hadoop 0 2015-05-08 12:40 delete/test2
咱們要刪除文件test1。下面的描述顯示文件已被移至垃圾桶目錄。
$ hadoop fs -rm -r delete/test1 Moved: hdfs://localhost:9820/user/hadoop/delete/test1 to trash at: hdfs://localhost:9820/user/hadoop/.Trash/Current
如今咱們將使用skipTrash選項刪除該文件,該選項不會將文件發送到Trash。它將從HDFS中徹底刪除。
$ hadoop fs -rm -r -skipTrash delete/test2
Deleted delete/test2
咱們如今能夠看到垃圾郵件目錄只包含文件test1。
$ hadoop fs -ls .Trash/Current/user/hadoop/delete/ Found 1 items\ drwxr-xr-x - hadoop hadoop 0 2015-05-08 12:39 .Trash/Current/user/hadoop/delete/test1
因此文件test1進入垃圾箱,文件test2被永久刪除。
當文件的複製因子減小時,NameNode選擇能夠刪除的多餘副本。下一個Heartbeat將此信息傳輸到DataNode。DataNode而後刪除相應的塊,而且相應的可用空間出如今羣集中。再次,在完成setReplication API調用和集羣中可用空間的外觀之間可能會有時間延遲。
Hadoop JavaDoc API.
HDFS source code: http://hadoop.apache.org/version_control.html