HDFS體系結構
HDFS采用了主從(Master/Slave)結構模型,一個HDFS集群包括一個名稱節點(NameNode)和若干個數據節點(DataNode)(如圖所示)。名稱節點作為中心服務器,負責管理文件系統的命名空間及客戶端對文件的訪問。集群中的數據節點一般是一個節點運行一個數據節點進程,負責處理文件系統客戶端的讀/寫請求,在名稱節點的統一調度下進行數據塊的創建、刪除和復制等操作。每個數據節點的數據實際上是保存在本地Linux文件系統中的。
HDFS體系結構的局限性
HDFS只設置唯一一個名稱節點,這樣做雖然大大簡化了系統設計,但也帶來了一些明顯的局限性,具體如下:
(1)命名空間的限制:名稱節點是保存在內存中的,因此,名稱節點能夠容納的對象(文件、塊)的個數會受到內存空間大小的限制。
(2)性能的瓶頸:整個分布式文件系統的吞吐量,受限於單個名稱節點的吞吐量。
(3)隔離問題:由於集群中只有一個名稱節點,只有一個命名空間,因此,無法對不同應用程序進行隔離。
(4)集群的可用性:一旦這個唯一的名稱節點發生故障,會導致整個集群變得不可用。
冗余數據保存
作為一個分布式文件系統,為了保證系統的容錯性和可用性,HDFS采用了多副本方式對數據進行冗余存儲,通常一個數據塊的多個副本會被分布到不同的數據節點上,如圖所示,數據塊1被分別存放到數據節點A和C上,數據塊2被存放在數據節點A和B上。這種多副本方式具有以下幾個優點:
(1)加快數據傳輸速度
(2)容易檢查數據錯誤
(3)保證數據可靠性
數據存取策略
1、數據存放
第一個副本:放置在上傳文件的數據節點;如果是集群外提交,則隨機挑選一台磁盤不太滿、CPU不太忙的節點
第二個副本:放置在與第一個副本不同的機架的節點上
第三個副本:與第一個副本相同機架的其他節點上
更多副本:隨機節點
2、數據讀取
HDFS提供了一個API可以確定一個數據節點所屬的機架ID,客戶端也可以調用API獲取自己所屬的機架ID
當客戶端讀取數據時,從名稱節點獲得數據塊不同副本的存放位置列表,列表中包含了副本所在的數據節點,可以調用API來確定客戶端和這些數據節點所屬的機架ID,當發現某個數據塊副本對應的機架ID和客戶端對應的機架ID相同時,就優先選擇該副本讀取數據,如果沒有發現,就隨機選擇一個副本讀取數據
數據錯誤與恢復
HDFS具有較高的容錯性,可以兼容廉價的硬件,它把硬件出錯看作一種常態,而不是異常,並設計了相應的機制檢測數據錯誤和進行自動恢復,主要包括以下幾種情形:名稱節點出錯、數據節點出錯和數據出錯。
1、名稱節點出錯
名稱節點保存了所有的元數據信息,其中,最核心的兩大數據結構是FsImage和Editlog,如果這兩個文件發生損壞,那么整個HDFS實例將失效。因此,HDFS設置了備份機制,把這些核心文件同步復制到備份服務器SecondaryNameNode上。當名稱節點出錯時,就可以根據備份服務器SecondaryNameNode中的FsImage和Editlog數據進行恢復。
2、數據節點出錯
每個數據節點會定期向名稱節點發送“心跳”信息,向名稱節點報告自己的狀態
當數據節點發生故障,或者網絡發生斷網時,名稱節點就無法收到來自一些數據節點的心跳信息,這時,這些數據節點就會被標記為“宕機”,節點上面的所有數據都會被標記為“不可讀”,名稱節點不會再給它們發送任何I/O請求
這時,有可能出現一種情形,即由於一些數據節點的不可用,會導致一些數據塊的副本數量小於冗余因子
名稱節點會定期檢查這種情況,一旦發現某個數據塊的副本數量小於冗余因子,就會啟動數據冗余復制,為它生成新的副本
HDFS和其它分布式文件系統的最大區別就是可以調整冗余數據的位置
3、數據出錯
網絡傳輸和磁盤錯誤等因素,都會造成數據錯誤
客戶端在讀取到數據后,會采用md5和sha1對數據塊進行校驗,以確定讀取到正確的數據
在文件被創建時,客戶端就會對每一個文件塊進行信息摘錄,並把這些信息寫入到同一個路徑的隱藏文件里面
當客戶端讀取文件的時候,會先讀取該信息文件,然后,利用該信息文件對每個讀取的數據塊進行校驗,如果校驗出錯,客戶端就會請求到另外一個數據節點讀取該文件塊,並且向名稱節點報告這個文件塊有錯誤,名稱節點會定期檢查並且重新復制這個塊
HDFS特點:
1、HDFS是一個高度容錯性的系統,適合部署在廉價的機器上。
2、HDFS能提供高吞吐量的數據訪問,非常適合大規模數據集上的應用。HDFS的設計中更多的考慮到了數據批處理,而不是用戶交互處理。比之數據訪問的低延遲問題,更關鍵的在於數據訪問的高吞吐量。
3、錯誤檢測和快速、自動的恢復是HDFS最核心的架構目標。
4、HDFS應用需要一個“一次寫入多次讀取”的文件訪問模型。一個文件經過創建、寫入和關閉之后就不需要改變
HDFS特殊的設計,在實現上述優良特性的同時,也使得自身具有一些應用局限性,主要包括以下幾個方面:
- 不適合低延遲數據訪問
- 無法高效存儲大量小文件
- 不支持多用戶寫入及任意修改文件
Namenode 和Datanode
Namenode:
管理文件系統的名字空間(namespace)以及客戶端對文件的訪問。記錄每個文件數據快在各個DataNode上的位置和副本信息,記錄命名空間內的改動或空間本身屬性的改動;協調客戶端對文件的訪問;NameNode使 用事物日志記錄HDFS元數據的變化,使用映像文件存儲文件系統的命名空間,
兩個核心的數據結構,即FsImage和EditLog
FsImage用於維護文件系統樹以及文件樹中所有的文件和文件夾元數據
操作日志文件EditLog中記錄了所有針對文件的創建、刪除、重命名等操作
FsImage文件
FsImage文件包含文件系統中所有目錄和文件inode的序列化形式。每個inode是一個文件或目錄的元數據的內部表示,並包含此類信息:文件的復制等級、修改和訪問時間、訪問權限、塊大小以及組成文件的塊。對於目錄,則存儲修改時間、權限和配額元數據。
FsImage文件沒有記錄塊存儲在哪個數據節點。而是由名稱節點把這些映射保留在內存中,當數據節點加入HDFS集群時,數據節點會把自己所包含的塊列表告知給名稱節點,此后會定期執行這種告知操作,以確保名稱節點的塊映射是最新的。
名稱節點的啟動
在名稱節點啟動的時候,它會將FsImage文件中的內容加載到內存中,之后再執行EditLog文件中的各項操作,使得內存中的元數據和實際的同步,存在內存中的元數據支持客戶端的讀操作。
一旦在內存中成功建立文件系統元數據的映射,則創建一個新的FsImage文件和一個空的EditLog文件。
名稱節點起來之后,HDFS中的更新操作會重新寫到EditLog文件中,因為FsImage文件一般都很大(GB級別的很常見),如果所有的更新操作都往FsImage文件中添加,這樣會導致系統運行的十分緩慢,但是,如果往EditLog文件里面寫就不會這樣,因為EditLog 要小很多。每次執行寫操作之后,且在向客戶端發送成功代碼之前,edits文件都需要同步更新。
名稱節點運行期間EditLog不斷變大的問題
在名稱節點運行期間,HDFS的所有更新操作都是直接寫到EditLog中,久而久之, EditLog文件將會變得很大
雖然這對名稱節點運行時候是沒有什么明顯影響的,但是,當名稱節點重啟的時候,名稱節點需要先將FsImage里面的所有內容映像到內存中,然后再一條一條地執行EditLog中的記錄,當EditLog文件非常大的時候,會導致名稱節點啟動操作非常慢,而在這段時間內HDFS系統處於安全模式,一直無法對外提供寫操作,影響了用戶的使用
如何解決?答案是:SecondaryNameNode第二名稱節點
第二名稱節點是HDFS架構中的一個組成部分,它是用來保存名稱節點中對HDFS 元數據信息的備份,並減少名稱節點重啟的時間。SecondaryNameNode一般是單獨運行在一台機器上
SecondaryNameNode的工作情況:
(1)SecondaryNameNode會定期和NameNode通信,請求其停止使用EditLog文件,暫時將新的寫操作寫到一個新的文件edit.new上來,這個操作是瞬間完成,上層寫日志的函數完全感覺不到差別;
(2)SecondaryNameNode通過HTTP GET方式從NameNode上獲取到FsImage和EditLog文件,並下載到本地的相應目錄下;
(3)SecondaryNameNode將下載下來的FsImage載入到內存,然后一條一條地執行EditLog文件中的各項更新操作,使得內存中的FsImage保持最新;這個過程就是EditLog和FsImage文件合並;
(4)SecondaryNameNode執行完(3)操作之后,會通過post方式將新的FsImage文件發送到NameNode節點上;
(5)NameNode將從SecondaryNameNode接收到的新的FsImage替換舊的FsImage文件,同時將edit.new替換EditLog文件,通過這個過程EditLog就變小了。
Datanode:
負責處理文件系統客戶端的讀寫請求。
數據節點是分布式文件系統HDFS的工作節點,負責數據的存儲和讀取,會根據客戶端或者是名稱節點的調度來進行數據的存儲和檢索,並且向名稱節點定期發送自己所存儲的塊的列表。
每個數據節點中的數據會被保存在各自節點的本地Linux文件系統中。
當一個Datanode啟動時,它會掃描本地文件系統,產生一個這些本地文件對應的所有HDFS數據塊的列表,然后作為報告發送到Namenode,這個報告就是塊狀態報告
名稱節點和數據節點
NameNode | DataNode |
存儲元數據 | 存儲文件內容 |
元數據保存在內存中 | 文件內容保存在磁盤 |
保存文件block,datanode之間的映射關系 | 維護了block id到datanode本地文件的映射關系 |
讀取數據流程:
客戶端要訪問HDFS中的文件,首先從NameNode獲取組成這個文件的數據塊位置列表,根據數據塊位置列表,知道存儲數據塊的DataNode,訪問DataNode獲取數據,NameNode並不參與數據實際傳輸。
數據復制:
Namenode全權管理數據塊的復制,它周期性地從集群中的每個Datanode接收心跳信號和塊狀態報告(Blockreport)。接收到心跳信號意味着該Datanode節點工作正常。塊狀態報告包含了一個該Datanode上所有數據塊的列表。
HDFS分布式文件系統的可靠性
- 副本冗余:在hdfs-site.xml中可以設置副本的數量,DataNode啟動時,首先會遍歷本地的文件系統,產生一份hdfs數據塊和本地文件的對應關系列表(blockreport)匯報給namenode。
- 機架策略:通過“機架感知”,將數據塊副本存儲在不同的機架中。
- 心跳機制:NameNode周期性的從datanode接受心跳信號和塊報告。根據塊報告驗證元數據,副本數量、磁盤錯誤、節點宕機。
- 安全模式:NameNode啟動時會經過“安全模式”階段,安全模式不會產生數據寫。可以通過命令強制集群進入安全模式。
- 校驗和:文件創立的時候,每個文件都會產生校驗和,校驗和會作為一個隱藏文件保存在命名空間下,客戶端獲取數據時可以檢查校驗和是否相同,從而法相數據塊是否損壞。
- 回收站:HDFS提供回收站功能。
- 元數據保護:映像文件和事物日志是Namenode的核心數據。可以配置為擁有多個副本,副本會降低Name的處理速度,但是增加安全性。
HDFS數據讀寫過程
讀取文件
寫入文件
讀數據的過程
寫數據的過程
安全模式
Namenode啟動后會進入一個稱為安全模式的特殊狀態。處於安全模式的Namenode是不會進行數據塊的復制的。Namenode從所有的 Datanode接收心跳信號和塊狀態報告。塊狀態報告包括了某個Datanode所有的數據塊列表。每個數據塊都有一個指定的最小副本數。當Namenode檢測確認某個數據塊的副本數目達到這個最小值,那么該數據塊就會被認為是副本安全(safely replicated)的;在一定百分比(這個參數可配置)的數據塊被Namenode檢測確認是安全之后(加上一個額外的30秒等待時間),Namenode將退出安全模式狀態。接下來它會確定還有哪些數據塊的副本沒有達到指定數目,並將這些數據塊復制到其他Datanode上。
Staging
客戶端創建文件的請求其實並沒有立即發送給Namenode,事實上,在剛開始階段HDFS客戶端會先將文件數據緩存到本地的一個臨時文件。應用程序的寫操作被透明地重定向到這個臨時文件。當這個臨時文件累積的數據量超過一個數據塊的大小,客戶端才會聯系Namenode。Namenode將文件名插入文件系統的層次結構中,並且分配一個數據塊給它。然后返回Datanode的標識符和目標數據塊給客戶端。接着客戶端將這塊數據從本地臨時文件上傳到指定的Datanode上。當文件關閉時,在臨時文件中剩余的沒有上傳的數據也會傳輸到指定的Datanode上。然后客戶端告訴Namenode文件已經關閉。此時Namenode才將文件創建操作提交到日志里進行存儲。如果Namenode在文件關閉前宕機了,則該文件將丟失。
流水線復制
當客戶端向HDFS文件寫入數據的時候,一開始是寫到本地臨時文件中。假設該文件的副本系數設置為3,當本地臨時文件累積到一個數據塊的大小時,客戶端會從Namenode獲取一個Datanode列表用於存放副本。然后客戶端開始向第一個Datanode傳輸數據,第一個Datanode一小部分一小部分(4 KB)地接收數據,將每一部分寫入本地倉庫,並同時傳輸該部分到列表中第二個Datanode節點。第二個Datanode也是這樣,一小部分一小部分地接收數據,寫入本地倉庫,並同時傳給第三個Datanode。最后,第三個Datanode接收數據並存儲在本地。因此,Datanode能流水線式地從前一個節點接收數據,並在同時轉發給下一個節點,數據以流水線的方式從前一個Datanode復制到下一個。
文件的刪除和恢復
當用戶或應用程序刪除某個文件時,這個文件並沒有立刻從HDFS中刪除。實際上,HDFS會將這個文件重命名轉移到/trash目錄。只要文件還在/trash目錄中,該文件就可以被迅速地恢復。文件在/trash中保存的時間是可配置的,當超過這個時間時,Namenode就會將該文件從名字空間中刪除。刪除文件會使得該文件相關的數據塊被釋放。注意,從用戶刪除文件到HDFS空閑空間的增加之間會有一定時間的延遲。
只要被刪除的文件還在/trash目錄中,用戶就可以恢復這個文件。如果用戶想恢復被刪除的文件,他/她可以瀏覽/trash目錄找回該文件。/trash目錄僅僅保存被刪除文件的最后副本。/trash目錄與其他的目錄沒有什么區別,除了一點:在該目錄上HDFS會應用一個特殊策略來自動刪除文件。目前的默認策略是刪除/trash中保留時間超過6小時的文件。將來,這個策略可以通過一個被良好定義的接口配置。
減少副本系數
當一個文件的副本系數被減小后,Namenode會選擇過剩的副本刪除。下次心跳檢測時會將該信息傳遞給Datanode。Datanode遂即移除相應的數據塊,集群中的空閑空間加大。同樣,在調用setReplication API結束和集群中空閑空間增加間會有一定的延遲。