Hadoop分布式文件系統:結構與設計
Hadoop 分布式文件系統 (HDFS)是一個設計為用在普通硬件設備上的分布式文件系統。它與現有的分布式文件系統有很多近似的地方,但又和這些文件系統有很明顯的不同。HDFS 是高容錯的,設計為部署在廉價硬件上的。HDFS對應用程序的數據提供高吞吐量,而且適用于那些大數據集應用程序。HDFS開放了一些POSIX的必須接 口,容許流式訪問文件系統的數據。HDFS最初是為了Apache 的Nutch網絡搜索引擎項目的下層構件而設計的。是Hadoop項目的一部分,而這又是Apache的 Lucene項目的一部分。本項目的地址是:http://projects.apache.org /projects/hadoop.html。
- 硬 件錯誤是正常的,而不是異常。HDFS實例由成百上千個服務器組成,每個都存儲著文件系統的一部分數據。事實上,這就會有大量的組件,而 每個組件出故障的可能性都很大,這意味著HDFS總有一些組件是不能工作的。因此,檢測錯誤并快速自動恢復就成了HDFS的核心設計目標。
- 運 行在HDFS上的應用程序需要流式的訪問它們的數據集,它們也不是通常運行在普通文件系統上的普通應用程序。HDFS為了那些批量處理而 設計的,而不是為普通用戶的交互使用。強調的是數據訪問的高吞吐量而不是數據訪問的低反應時間。POSIX強加的很多硬性需求是HDFS上應用程序所不需 要的, 這些POSIX語義在一些關鍵環境下被用來提高數據的吞吐頻率。
- 運行在HDFS上的應用程序 使用大數據集。HDFS一個典型的文件可能是幾GB的或者幾TB的。因此,HDFS適用于大文件。這將提供高集成帶寬,并在一幾集群中提供上百個結點。一 個實例可能支持上千萬個文件。
HDFS的應用程序需要對文件實行一次性寫,多次讀的訪問模式。文件一 旦建立后寫入,文件就不需要再更改了。這樣的假定簡化了數據一致性問題并使高數據吞吐量成為可能。MapReduce程 序或者網絡爬蟲程序就很適合使用這樣的模型。當然未來計劃支持增量寫。
如 果就在數據的旁邊就執行對這些數據的操作,那么程序所使用的設備就會 很高效。這當文件相當巨大的時候就尤其正確。這可以減少網絡的擁塞和提高系統的吞吐量。這個假設還意味著,常常是把計算遷移到數據存儲的近處更好,而不是 把數據傳輸到程序運行的地方。HDFS提供了程序接口以便把他們自己移動到數據存儲的地方執行。
- HDFS設計為容易的從一個 平臺移動到另一個平臺。這有助于HDFS被采用做為一個大程序集合的工作平臺。
- HDFS 是主/從結構的。一 個集群有一個名字結點,也就是主控制服務器,負責管理文件系統的名字空間并協調客戶對文件的訪問。還有一堆數據結點,一般一個物理結點上部署一個,負責它 們所在的物理結點上的存儲管理。HDFS開放文件系統的名字空間以便讓用戶數據存儲的文件中。內部,一個文件被分割為一個或者多個數據塊,這些數據塊存儲 在一組數據結點中。名字結點執行文件系統的名字空間操作,比如打開、關閉、重命名文件或目錄,還決定數據塊從數據結點的映射。數據結點負責提供客戶的讀寫 請求。數據結點還依照名字結點的指令執行數據塊的創建、刪除復制工作。
名字結點和數據結點是設計為運行在普 通機器上的軟件組件。這些機器大多運行GNU/Linux操作系統。HDFS使用 JAVA語言來實現;任何支持JAVA的機器都可以運行名字結點和數據結點軟件。使用高度可以移植的JAVA語言意味著HDFS可以被很多種機器使用。一 個典型的部署有一臺指定的機器只運行名字結點,體系結構并不排除在那臺機器上也運行數據結點,但是現實中的部署很少那樣使用。
一個集群中只有一個名字結點大大簡化了系統機構。名字結點做為所有系統元數據的存儲和仲裁者。系統這樣設計就會使用戶 數據從不會流經名字結點。
HDFS 支持傳統的文件組 織體系結構。用戶或者程序可以創建目錄,并在目錄中存儲文件。名字空間的結構和大多現有文件系統類似。你可以創建、刪除文件,把文件從一個目錄移動到另一 個目錄,或者重命名文件。HDFS還沒有實現用戶配額和訪問權限控制,也不支持硬連接和軟連接。當然體系也不妨礙實現這些特性。
- 名字結點維護系統的名字空間,它將記錄名字空間內的任何改動或者名字空間本身的屬性改 動。用戶可以指定HDFS中文件復制的份數,這個份數稱為復制因子,由名字結點記錄。
HDFS 被設計為在一個大 集群里跨機器、可靠的存儲非常大的文件。每個文件都存儲為一系列的塊,同一文件中除最后一塊以外的所有塊都是一樣大的。文件的塊都通過復制來保證容錯。每 個文件的塊的大小和復制因子都是可以配置的。程序可以指定文件復制的次數,復制因子可以在文件創建時候指定,也可以在以后指定。HDFS的文件都是一次性 寫入的,并且嚴格限制任何時候都只有一個寫用戶。
名字結點根據塊復制狀態做出所 有決定,它會周期的收到來自集群內數據結點的心跳和塊報告。能收到心跳證明數據結點工作是正常的。一個塊報告應該包括數據結點上所有塊的列表。
復 制品的位置對于HDFS的可靠性和性能來說是很關鍵的,和其他分布式 文件系統最大的區別就是它能優化復制品的位置,這個特性需要大量的調整和經驗。小心衡量復制品的放置是為了提高數據的可靠性、可用性、網絡帶寬利用率。目 前對于復制品放置的策略只是朝這個方向努力的第一步,短期的目標是要在生產系統中驗證,更多學習它的行為,并建立一個基礎來測試和研究更復雜的策略。
大的HDFS實體在一大堆機器上運行著,這些機器可能要跨幾個機柜來放。不同柜子里的兩個結點通信的時候要通過交換 機。大多數情況下,同一個機柜的機器間的帶寬比不同機柜的機器間的帶寬要大。
啟 動的時候,每個數據結點確 定自己所在的機柜并通知名字結點注冊表中此機柜的ID。HDFS提供一些API,以方便可拆卸模塊用來確定自己所在的機柜的ID。 有個簡單但不是很理想的策略是:在不同機柜上放置復制品。這防止在整個機柜宕掉的時候丟失數據,還容許在讀數據的時候使用多個機柜的帶寬。這個策略還可以 均勻的放置復制品,以便在組件失敗的時候平衡負載。但是,這個策略會增加寫的代價,寫操作需要跨機柜的傳輸數據塊。
對于 一般的情況,當復制因子是3的時候,HDFS的部署策略是:在本地機柜放置一個結點,此機柜再放一個不同的結點, 然后在另一個機柜放一個結點。這樣的策略砍掉了機柜內部寫操作的傳輸,這將提高了寫的性能。機柜壞掉的概率比一個結點壞掉的概率要小的多;這個策略不會影 響數據的可靠性和可用性的保證。 實際上,當從兩個不同的機柜上讀數據塊的時候,對比從三個上讀,并不減少總使用帶寬。使用此策略,文件的復制品不能跨機柜均勻的分配。
1/3的復制品放在一個結點上,(這樣就有)2/3復制品放在同一個機柜上,最后的1/3均勻的放在其他的機柜的結點 上。
這個策略提高了寫的性能而沒有對數據可靠性或讀性能造成損失。 當前,缺省的復制品放置策略,也就是這里討論的策略還是一個正在進行中的工作。
為 了減少總帶寬消耗和讀延時,HDFS會試圖使用離讀客戶最近的復制品 來滿足讀請求。如果在讀結點的同一個機柜有一個復制品,那么這個復制品將是最合適滿足這個讀請求的。如果HDFS機群跨了多個數據中心,那么駐留在本地數 據中心的復制品就比遠程的復制品更合適。
啟 動的時候,名字結點進入一個特殊的狀態叫做安全模式,此時不會出現數 據塊的復制。名字結點會收到數據結點的心跳和數據塊報告。數據塊報告包括一個數據結點所擁有的數據塊列表。每個數據塊里都有指定數目的復制品。當某個名字 結點登記過數據復制品的最小數目,數據塊就被認為是安全復制了。在那么可配置百分比安全復制的數據塊在名字結點登記后(加上附加的30秒),名字結點退出 安全模式。它將確定數據塊(如果有的話)比指定的復制品數據要少的那些,然后對這些數據塊進行復制。
HDFS 的命名空間存儲在 名字結點上,名字結點使用叫做“編輯日志”的事務日志來持久化記錄文件系統元數據的每次變化。例如,當在HDFS中創建一個文件的時候,名字結點就會在 “編輯日志”中插入一條記錄。類似的,當文件的復制因子也會引起一條新的記錄被插入“編輯日志”。名字結點使用本地操作系統的文件才存儲“編輯日志”。整 個文件系統的命名空間,包括塊到文件的影射,文件系統的屬性,都存儲在一個叫做“文件系統鏡象”的文件里,這個文件也是放在名字結點本地操作系統上的。
名 字結點在內存里保持一份含有整個系統的命名空間以及文件塊影射的鏡象。關鍵的元數據條目設計的很簡潔,這樣一個有 4GB內存的名字結點就足以支持大量的目錄和文件。當名字結點啟動的時候,它會從磁盤讀取“文件系統鏡象”和“編輯日志”,把“編輯日志”的事務都應用到 內存中的文件鏡象上,然后在新的文件鏡象刷新到硬盤上,這時因為事務因為已經被持久化了,就可以把舊的“編輯日志”截短了。這個過程叫做檢查點。在當前的 實現中,檢查點只出現在名字結點啟動的時候,關于在未來支持周期性檢查點的工作還在進行中。
數據結點使用本地文件系統來 存儲HDFS的數據。數據結點對HDFS的文件一無所知,它只是用一個個文件存儲HDFS的 每個數據塊。數據結點并不在同一個目錄中創建所有的文件,而是用一個啟發式算法來確定每個目錄的最佳文件個數,并適當的建立字目錄。在同一個目錄建立所有 的文件不是最理想的,這是因為本地文件系統可能不支持在同一個目錄放數目巨多的文件。當數據結點啟動的時候,它會遍歷本地文件系統,會產生一份HDFS數 據塊和本地文件對應關系的列表,并把這個報告發給名字結點:這就是塊報告。
HDFS 的所有通信協議都是在TCP/IP協議上層分層的。客戶去連接 名字結點上一個可配置的TCP端口,使用“客戶協議”與名字結點交互。數據結點和名字結點使用“數據結點協議”交互。一個遠程過程調用(RPC)則封裝了 這兩個協議。按照設計,名字結點永遠不會啟動任何的RPC,它只負責響應數據結點或客戶發起的請求。
HDFS的首要目的就是要保證數據的可靠性,甚至出錯的時候也是。三個 最常見的錯誤就是,名字結點或數據結點故障,和網絡斷開。
每 個數據結點都周期性的向名字結點發送心跳數據包。網絡阻斷可能會造成 一些數據結點失去到名字結點的連接。名字結點通過心跳的丟失來檢測這樣的情況。名字結點會標記沒有最近沒有心跳的數據結點為宕機,并不轉發給他們任何新的 IO請求。任何注冊在已宕機數據結點的數據對HDFS來說都是不在可用的了。數據結點的宕機會造成一些數據塊的復制因子下降并低于指定值。名字結點會一直 跟蹤哪些數據塊需要被復制,并在需要的時候開始復制。這樣必要的重復制的引發可能有多種原因:數據結點不可用,一個復制品損壞,數據結點上某個磁盤損壞, 某個文件復制因子被提升了。
HDFS 的結構是和數據重配平方案相適應的。如果某個數據結點的剩余磁 盤空間下降到某個極限,方案自動把數據從此數據結點移動到另一個結點。當出現對某個文件有很高的需求的時候,方案會動態增加更多的復制品,并平衡機群中的 其他數據。這些數據配平方案還沒有實現。
有種可能 是從數據結點拿到的數據卻是損壞的,這樣的錯誤可能是由于存儲 設備錯誤,網絡故障或者軟件的BUG。HDFS的客戶軟件實施對HDFS文件內容的校驗和檢查。當一個客戶創建HDFS文件,它先計算文件每個塊的校驗 和,并存儲到同命名空間下的隱藏文件里。 當客戶收到文件內容后,會檢查各個數據結點取出的數據和相應的校驗和相匹配。如果不匹配那么客戶就選擇其他有復制品的數據結點取一份數據。
- “文件系統鏡象”和“編輯日 志”是HDFS的中心重要結構,這些文件損壞了會導致HDFS實例不可用。
因 此,名字結點可以配置為支持保存“文件系統鏡象”和“編輯日志”的多份拷貝。它們的每次更新,都會引發文件的多份拷 貝的同步更新。但是這樣的同步會降低名字結點上命名空間的傳輸速度。實際上,變慢的程度是可以接受的,因為即便是程序是對數據非常的敏感,但是也不是對元 數據敏感。當名字結點重新啟動的時候,它回選擇最新的文件拷貝。 名字結點機器只是HDFS機群的一個單點故障。如果名字結點真的宕掉了,那么手動干預就是必須的了。當前,對命名結點自動重啟或把宕掉的軟件恢復到其他機 器上還不支持。
快照支持存儲某一點時間的數據拷貝。這個特性的一個應用就是:把損壞的 HDFS實例回滾到以前某個正常的時間點。目前還不支持這個特性,未來版本會支持。
HDFS 被設計為支持非常大的文件。并且與HDFS相一致的程序也是 處理大數據集的。程序一次性寫入數據,但是會一次或多次讀取,并希望能得到線速的讀取。HDFS支持文件語義上一次寫多次讀,它所使用的塊大小通常是 64M。因此,HDFS的文件都被切割為64M的塊,還有可能,每個數據塊駐留在不動的數據結點上。
客 戶創建文件的請求不是立即到達名字結點,而是HDFS客戶把數據緩 存到本地的一個文件里。程序的寫操作顯式重定向到這個本地臨時文件。當本地的文件積聚的數據超過了HDFS數據塊的大小客戶才和名字結點聯系。名字結點在 系統的體系中插入文件名,并申請一個數據塊給它。名字結點應答給客戶數據結點的的ID和目標數據塊ID,這樣客戶就把數據從本地的緩存刷新到目的的數據塊 中。當文件關閉后,臨時文件中剩余的未刷新數據也會被傳輸到數據結點中,客戶這時就可以告訴名字結點文件被關閉了。這一時間點,名字結點完成了在持久存儲 中創建文件的操作。如果名字結點在文件關閉之前宕掉了,那么文件就丟失了。
在對運行HDFS在上應用 軟件仔細權衡以后,上述的方法已經被接受了。這些程序需要流式寫入到文件。如果客戶直接寫到遠程的文件而沒有任何緩存的話,網絡中的速度和擁塞就會對輸出 影響很大。這樣的方法也不是沒有先例。早期的分布文件系統比如,AFS就已經采用了客戶緩存來提高性能。為了得到數據上傳的更好性能,POSIX的相關要 求已經被放棄不用了。
當客戶要寫 數據到HDFS的文件中,就象前一節解釋的那樣,數據會首 先寫到一個本地文件里。假設HDFS文件的復制因子是3,當本地文件積聚到數據塊那么大的時候,用戶從名字結點獲得一個數據結點列表,列表中的數據結點都 將保存那個數據塊一份拷貝。客戶就把數據塊刷新到第一個數據結點上,這個結點開始用(4K)的小塊來接收數據,把每個塊寫到本地庫中,并傳遞給列表中的第 二個數據結點,第二個結點開始每個小數據塊,寫到自己本地庫中,并把這塊數據刷新給第3個結點。最后,第3個結點把數據寫到自己的庫中。因此,數據結點就 可以同時從前一個結點那里收數據,并同時流水線的把數據傳給后面的數據結點。也就是,數據形成了流水線,從一個數據結點傳遞給下一個。
從應用程序有很多方式訪 問HDFS,自然而然的,它提供了一組Java API供程序使用。 并且對這組API的C語言封裝也是可用的。HTTP瀏覽器也可以用來瀏覽一個HDFS實例的文件。使用WebDAV協議訪問的工作還在進行中。
HDFS使用文件和目錄的形式組織用戶的數據,它提供了命令接口 DFSShell讓用戶和其中的數據交互。這些命令的語法和其他用戶已經熟悉的Shell都很相似,這里提供了一個示例:
HDFS 管理命令組是為了管理一個HDFS機群而設計的,這些命令只 能由管理員來使用,這里是一些示例: Action Command Put a cluster in SafeMode bin/hadoop dfsadmin -safemode enter Generate a list of Datanodes bin/hadoop dfsadmin -report Decommission Datanode datanodename bin/hadoop dfsadmin -decommission datanodename
一個典型的HDFS安裝會配置一個WEB服務器開放自己的命名空間, 其TCP端口是可配的。這樣用戶就可以通過WEB瀏覽器遍歷HDFS的命名空間并查看文件內容。
當 文件被用戶或者程序刪除了,并不是立即就從HDFS中移走了。而是 HDFS先把它移動到/trash目錄里。只要還在這個目錄里,文件就可以被恢復。文件在這個目錄里的時間是可以配置的,超過了生命周期,系統就把它從命 名空間中刪除了。文件的刪除操作會引起相應數據塊的釋放。注意一點:從用戶執行刪除操作到從系統中看到剩余空間的增加可能需要相當長的時間。
用 戶可以在刪除后取消操作,只要文件還在回收站里。當用戶想取消的時候,可以瀏覽這個目錄,并取回文件。這個目錄只包 含最近被刪除的文件,這個目錄有個特性就是HDFS使用策略自動刪除文件。當前默認的策略是:超過6個小時以后自動刪除文件。在未來版本里,這個策略是一 個通過良好定義的接口來配置的。
當 一個文件發復制因子減低了,名字結點會選出一些多處的可以刪除的復 制品。下一個心跳將傳遞這些信息到數據結點,數據結點就刪除相應的塊,機群中就會出現相應的剩余空間。再一次說明,當調用setReplication函 數和看到剩余空間之間會有一個延時。
HDFS Java API: http://lucene.apache.org/hadoop/api/ HDFS source code: http://lucene.apache.org/hadoop/version_control.html
問題: 1) 名字結點的穩定性 2) 多進程同時訪問的安全性 3) 小文件怎么解決