Hadoop详解(二):HDFS存储系统设计原理
1. 基本概念
1.1 NameNode
HDFS采用Master/Slave架構。NameNode就是HDFS的Master架構。HDFS系統包括一個NameNode組件,主要負責HDFS文件系統的管理工作,具體包括名稱空間(namespace)管理,文件Block管理。NameNode提供的是始終被動接收服務的server,主要有三類協議接口:
- ClientProtocol接口,提供給客戶端,用于訪問NameNode。它包含了文件的HDFS功能。和GFS一樣,HDFS不提供POSIX形式的接口,而使用了一個私有接口。
- DataNodeProtocol接口,用于DataNode向NameNode通信。
- NameNodeProtocol接口,用于從NameNode到NameNode的通信。
在HDFS內部,一個文件被分成一個或多個Block,這些Block存儲在DataNode集合里,NameNode就負責管理文件Block的所有元數據信息,這些元數據信息主要為:
- “文件名→數據塊”映射
- “數據塊→DataNode列表”映射
- 文件owership和permissions(文件權限)
- 文件大小,時間
其中,“文件名→數據塊”保存在磁盤上進行持久化存儲,需要注意的是NameNode上不保存“數據塊→DataNode列表”映射,該列表是通過DataNode上報給NameNode建立起來的。
1.2 SecondaryNameNode
SecondaryNameNode其主要是定時對NameNode的數據snapshots進行備份,這樣可盡量降低NameNode崩潰之后導致數據丟失的風險,其所做的工作就是從NameNode獲得fsimage和edits后把兩者重新合并發給NameNode,這樣,既能減輕NameNode的負擔又能安全地備份,一旦HDFS的Master架構失效,就可以借助Secondary NameNode進行數據恢復。SecondaryNameNode的主要工作是幫助NameNode合并edits log,減少NameNode的啟動時間。
1.3 DataNode
DataNode就是負責存儲數據的組件,一個數據塊Block會在多個DataNode中進行冗余備份;而一個DataNode對于一個塊最多只包含一個備份。所
以可以簡單地認為DataNode上存儲了數據塊ID和數據塊內容以及它們的映射關系。
過DataNode啟動時的上報來更新NameNode上的映射表。DataNode和NameNode建立連接后,就會不斷地和NameNode保持聯系,反饋信息中也包含了NameNode對DataNode的一些命令,如
刪除數據庫或者把數據塊復制到另一個DataNode。當然DataNode也作為服務器接受來自客戶端的訪問,處理數據塊讀/寫請求。DataNode之間還會進行通信,執行數據塊復制的任務。
1.4 客戶端
訪問HDFS的程序或HDFS shell命令都可以稱為HDFS的客戶端(client),在HDFS的客戶端中至少需要指定HDFS集群配置中的NameNode地址以及端口號信息,或者通過配
置HDFS的core-site.xml配置文件來指定。
1.5 塊(Block)
HDFS為了滿足大數據的效率和整個集群的吞吐量選擇了更大的數值,默認是128M。
客戶端在讀取HDFS上的一個文件時就以塊為基本的數據單元。例如一次簡單讀取,首先,客戶端把文件名和程序指定的字節偏移,根據固定的Block大小,轉換成文件的Block索引。然后,客戶端把文件名和Block索引發送給Master節點,Master節點將相應的Block標識和副本的位置信息返回給客戶端,客戶端用文件名和Block索引作為key緩存這些信息,之后客戶端發送請求到其中的一個副本,一般會選擇最近的。請求信息包含了Block的標識和字節范圍。在對這個Block的后續讀取操作中,客戶端不必再和Master節點通信了,除非緩存的元數據信息過期或文件被重新打開。實際上,客戶端通常會在一次請求中查詢多個Block信息,Master節點的回應也可能包含了緊跟著這些被請求的Block后面的Block的信息。在實際應用中,這些額外的信息在不花費任何代價的情況下,避免了客戶端和Master節點未來可能會發生的幾次通信。
2. HDFS的特性和目標
2.1 HDFS的特性
- 高容錯,可擴展以及可配置性強
- 跨平臺
- Shell命令接口
- Web界面
- 文件權限和授權。
- 機架感知功能。
- 安全模式。
- Rebalacner。
- 升級和回滾程序。
2.2 HDFS的目標
- 硬件錯誤
- 流式數據的訪問
- 大規模數據集
- 簡化一致性模型
- 移動計算代價比移動數據代價低
- 可移植性
3. HDFS架構
NameNode負責管理文件系統的命令空間和客戶端對文件的訪問:DataNode是數據存儲節點,所有的這些集群通常是普通運行的Linux機器,運行著用戶級別的服務進程。
3.1 Master/Slave架構
HDFS架構如下圖所示:
NameNode負責保存和管理所有的HDFS元數據,因而用戶數據就不需要通過NameNode,也就是說文件數據的讀寫是直接在DataNode上進行的。在默認情況下,HDFS使用三個冗余備份,當然用戶可以為不同的文件命名空間設定不同的復制因子。Namenode管理所有的文件系統元數據。這些數據包括空間、訪問控制信息、文件和Block的映射信息,以及當前Block的位置信息。
客戶端利用NameNode的通信只獲取元數據,所有的數據操作都是由客戶端直接和DataNode服務器進行交互的。
3.2 NameNode和SecondaryNameNode通信模型
NameNode將對文件系統的改動追加保存到本地文件系統上的一個日志文件edits。當一個NameNode啟動時,它首先從一個映像文件(fsimage)中讀取HDFS的狀態,接著執行日志文件中的編輯操作。然后將新的HDFS狀態寫入fsimage中并使用一個空的edits文件開始正常操作。因為NameNode只有在啟動階段才合并fsimage和edits,久而久之日志文件可能會變得非常龐大,特別是對于大型的集群日志文件太大的另一個副作用是下一次NameNode啟動會花很長時間,NameNode和Secondary NameNode之間的通信示意圖如圖
NameNode和Secondary NameNode間數據的通信使用的是HTTP協議,SecondaryNameNode定期合并fsimage和edits日志,將edits日志文件大小控制在一個限度下。因為內存需求和NameNode在一個數量級上,所以通常Secondary NameNode和NameNode運行在不同的機器上。Secondary NameNode通過bin/start-dfs.sh在conf/masters中指定的節點上啟動。
Secondary NameNode的檢查點進程啟動,是由以下兩個配置參數控制的
- fs.checkpoint.period 指定兩次連續檢查點的最大時間間隔,默認是一個小時。
- fs.checkpoint.size 定義了日志文件的最大值,一旦超過這個值就會導致強制執行檢查點,默認是64M
3.3 文件讀取機制
在讀取HDFS的文件時,首先客戶端調用FileSystem的open()函數打開文件,DistributedFileSystem用RPC調用元數據節點,得到文件的數據塊信息。對于每一個數
據塊,元數據節點返回保存數據塊的數據節點的地址。DistributedFileSystem返回FSDataInputStream給客戶端,用來讀取數據。客戶端調用stream的read()函數開始讀
取數據。DFSInputStream連接保存此文件第一個數據塊的最近的數據節點。Data從數據節點讀到客戶端,當此數據塊讀取完畢時,DFSInputStream關閉和此數據節點的連
接,然后連接此文件下一個數據塊的最近的數據節點。當客戶端讀取完數據的時候,調用FSDataInputStream的close函數。客戶端讀取HDFS中的文件訪問數據流的整個過程
如圖所示。圖中的操作序號1、2、3、4、5表示執行順序,讀取文件的數據流步驟如下:
1)調用FileSystem的open()打開文件,見序號1:open。
2)DistributedFileSystem使用RPC調用NameNode,得到文件的數據塊元數據信息,并返回FSDataInputStream給客戶端,見序號2:get block locations
3)HDFS客戶端調用stream的read()函數開始讀取數據,見序號3:read。
4)調用FSDataInputStream直接從DataNode獲取文件數據塊,見序號4 5read。
5)讀完文件時,調用FSDataInputStream的close函數,見序號6:close。
3.4 文件寫入機制
首先客戶端調用create()來創建文件,然后DistributedFileSystem同樣使用RPC調用NameNode元數據節點,在文件系統的命名空間中創建一個新的文件。
NameNode首先確定文件原來不存在,以及客戶端有創建文件的權限,然后創建新文件。
DistributedFileSystem返回DFSOutputStream,客戶端用于寫數據。客戶端開始寫入數據,DFSOutputStream將數據分成塊,寫入Data Queue。Data Queue由Data
Streamer讀取,并通知元數據節點分配數據節點,用來存儲數據塊(每塊默認復制3塊)。
分配的數據節點放在一個pipeline里。Data Streamer將數據塊寫入pipeline中的第一個數據節點。第一個數據節點將數據塊發送給第二個數據節點,第二個數據節點將
數據發送給第三個數據節點。
DFSOutputStream為發出去的數據塊保存了Ack Queue,等待pipeline中的數據節點告知數據已經寫入成功。如果數據節點在寫入的過程中失敗,
則關閉pipeline,同時將Ack Queue中的數據塊放入Data Queue的開始位置。
4. HDFS核心設計
4.1 Block大小
- 選擇較大的Block尺寸有幾個優點:首先,它減少了客戶端和NameNode通信的需求,因為只需要一次和NameNode節點的通信就可以獲取Block的位置信息,之后就可以通過對同一個Block進行多次的讀寫操作。
- 結合惰性空間分配,采用較大的Block尺寸也有缺陷。小文件包含較少的Block,甚至只有一個Block,當有許多的客戶端對同一個小文件進行多次訪問的時候,存儲這些Block的DataNode服務器就會變成一個訪問熱點。
4.2 數據復制
HDFS被設計成在一個大集群中可以跨機器可靠地存儲海量的文件。它將每個文件存儲成Block序列,除了最后一個Block,所有的Block都是同樣的大小。文件的所有Block為了容錯都會被冗余復制存儲。每個文件的Block大小和Replication因子都是可配置的。
4.3 數據副本存放策略
副本的存放是HDFS可靠性和高性能的關鍵。優化的副本存放策略是HDFS區分于其他大部分分布式文件系統的重要特性。這種特性需要做大量的調優,并需要經驗的積累。HDFS采用一種稱為機架感知(rack-aware)的策略來改進數據的可靠性、可用性和網絡帶寬的利用率。
在這種策略下,副本并不是均勻分布在不同的機架上。三分之一的副本在一個節點上,三分之一的副本在同一個機架的其他節點上,其他副本均勻分布在剩下的機架中,這一策略在不損害數據可靠性和讀取性能的情況下改進了寫的性能。
為了降低整體的帶寬消耗和讀取延時,HDFS會盡量讓讀取程序讀取離它最近的副
本。如果讀取程序的同一個機架上有一個副本,那么就讀取該副本;如果一個HDFS集群跨越多個數據中心,那么客戶端也將首先讀取本地數據中心的副本。
4.4 數據組織
4.4.1 數據塊
HDFS最適合的應用場景是處理大數據集合,同時這些應用大多是一次寫入多次讀取,并且讀取的數據要滿足流式讀取,即write-once-read-many語義。
4.4.2 Staging
事實上,HDFS客戶端會將文件數據緩存到本地的一個臨時文件中,應用寫文件時被透明地重定向到這個臨時文件。當這個臨時文件累積的數據超過一個Block的大小(默認為64MB),客戶端才會聯系NameNode。NameNode將文件名插入文件系統的層次結構中,并且分配一個數據塊給它,然后返回DataNode的標識符和目標數據塊給客戶端。客戶端將本地臨時文件flush到指定的DataNode上。當文件關閉時,在臨時文件中剩余的沒有flush的數據也會傳輸到指定的DataNode,然后客戶端告訴NameNode文件已經關閉。此時NameNode才將文件創建操作提交到持久存儲如果NameNode在文件關閉前掛機,該文件將丟失。
4.4.3 流水線式的復制
當某個客戶端向HDFS文件寫數據的時候,一開始是寫入本地的臨時文件,假設該文件的replication因子為3,那么客戶端會從NameNode獲取一張DataNode列表來存放副本。然后客戶端開始向第一個DataNode傳輸數據,第一個DataNode會一小部分一小部分(4KB)地接收數據,將每個部分寫入本地倉庫,同時傳輸該部分到第二個DataNode。第二個DataNode也是這樣,邊收邊傳,一部分一小部分接收,將每個部分存儲到本地倉庫。
4.5 空間回收
4.5.1 文件的刪除和恢復
當用戶或應用程序刪除某個文件,這個文件并沒有立刻從HDFS中刪除。而是被轉移到trash目錄下。
4.5.2 減少副本系數
在減少某個文件的副本系數之后,NameNode會選擇要刪除過剩的副本。下次心跳檢查就將該信息傳遞給DataNode,DataNode就會移除相應的Block并釋放空間。
4.6 通信協議
所有的HDFS的通信協議都是構建在TCP/IP之上的
4.7 安全模式
安全模式是這樣一種特殊狀態:當系統處于這個狀態時,不接受任何對名稱空間的修改,同時也不會對數據塊進行復制或刪除。NameNode在啟動的時候會自動進入安全模式,也可以手動進入(不會自動離開)。NameNode從所有的DataNode接收心跳信號和塊狀態報告。塊狀態報告包括了某個DataNode所有的數據塊列表,每個數據塊都有一個指定的最小副本數。當NameNode檢測確認某個數據塊的副本數目達到這個最小值時,該數據塊就會被認為是副本安全(safely replicated)的;在一定百分比(這個參數可配置)的數據塊被NameNode檢測確認是安全的之后(加上一個額外的30秒等待時間),NameNode將退出安全模式狀態。
NameNode退出安全模式之后會確定還有哪些數據塊副本沒有達到指定的數目,并將這些數據復制到其他DataNode上去。
4.8 機架感知
在通常情況下,大型Hadoop集群是以機架的形式來組織的,同一個機架上不同節點間的網絡狀況比不同機架之間的更為理想。需要程序員進行手動配置。
4.9 健壯性
HDFS的主要目標就是實現在失敗情況下數據存儲的可靠性。常見的三種失敗情況是:NameNode failures、DataNode failures和網絡分割(network partitions),這
幾種失敗很容易導致HDFS中的組件失效。下面將分別從數據錯誤、集群均衡、數據完整性、元數據磁盤錯誤,以及快照五個方面闡述HDFS的健壯性設計
4.9.1.數據錯誤
每個DataNode都向NameNode周期性地發送心跳包。網絡切割可能會導致部分DataNode與NameNode失去聯系。NameNode可通過心跳包的缺失檢測到這一情況,并將這些DataNode標記為dead,不會向它們發送IO請求,寄存在deadDataNode上的任何數據將不再有效。
4.9.2 集群均衡
HDFS支持數據的均衡計劃,如果某個DataNode上的空閑空間低于特定的臨界點,那么就會啟動一個計劃——自動將數據從一個DataNode搬移到空閑的DataNode。
4.9.3 數據完整性
從某個DataNode獲取的數據塊有可能是已損壞的,損壞可能是由于DataNode的存儲設備錯誤、網絡錯誤或者軟件bug造成的。HDFS客戶端軟件實現了HDFS文件內容的校驗和。當某個客戶端創建一個新的HDFS文件,會計算這個文件的每個Block的校驗和,并作為一個單獨的隱藏文件保存這些校驗和在同一個HDFS namespace下。當客戶端檢索文件內容,它會確認從DataNode獲取的數據跟相應的校驗和文件中的校驗和是否匹配,如果不匹配,客戶端可以選擇從其他DataNode獲取該Block的副本。
4.9.4 元數據磁盤錯誤
FsImage和Editlog是HDFS的核心數據結構。這些文件如果損壞了,整個HDFS實例都將失效。因而,NameNode可以配置成支持維護多個FsImage和Editlog的副本。任何
對FsImage或Editlog的修改,都將同步到它們的副本上。
4.9.5 快照
快照支持某個時間的數據副本,當HDFS數據損壞的時候,可以恢復到過去一個已知的正確時間點
5. 負載均衡
當新增一個數據塊(一個文件的數據被保存在一系列的塊中)時,NameNode在選擇DataNode接收這個數據塊之前,要考慮到很多因素。其中的一
些因素如下:
- 將數據塊的一個副本放在正在寫這個數據塊的節點上。
- 盡量將數據塊的不同副本分布在不同的機架上,這樣集群可在完全失去某一機架的情況下還能存活。
- 一個副本通常被放置在和寫文件的節點同一機架的某個節點上,這樣可以減少跨越機架的網絡I/O。
- 盡量均勻地將HDFS數據分布在集群的DataNode中。
由于上述多種考慮需要取舍,數據可能并不會均勻分布在DataNode中。當HDFS出現不平衡狀況的時候,將引發很多問題,比如MapReduce程序無法很好地利用本地計算的優勢,機器之間無法達到更好的網絡帶寬使用率、機器磁盤無法利用等。可見,保證HDFS中的數據平衡是非常重要的。為此,HDFS為管理員提供一個工具,用于分析數據分布和重新均衡DataNode上的數據分布:
$HADOOP_HOME/bin/start-balancer.sh -t 10%
-t參數后面跟的是HDFS達到平衡狀態的磁盤使用率偏差值。如果機器與機器之間磁盤使用率的偏差值小于10%。那么我們就可以認為HDFS集群已經達到了平衡狀態。
負載均衡程序作為一個獨立的進程與NameNode進行分開執行。從圖中可以看到,HDFS負載均衡的處理步驟如下:
1)負載均衡服務Rebalancing Server從NameNode中獲取所有的DataNode情況,具體包括每一個DataNode磁盤使用情況,見圖3-7中的流程1.get datanode report。
2)Rebalancing Server計算哪些機器需要將數據移動,哪些機器可以接受移動的數據,以及從NameNode中獲取需要移動數據的分布情況,見圖3-7中的流程2.get partial
blockmap。
3)Rebalancing Server計算出來可以將哪一臺機器的Block移動到另一臺機器中去,見圖中流程3.copy a block。
4)需要移動Block的機器將數據移動到目標機器上,同時刪除自己機器上的Block數
據,見圖中的流程4、5、6。
5)Rebalancing Server獲取本次數據移動的執行結果,并繼續執行這個過程一直到沒有數據可以移動或HDFS集群已經達到平衡的標準為止,見圖中的流程7。
6. HDFS權限管理
HDFS系統實現了一個和POSIX系統類似的文件和目錄權限管理模型。每個用戶和目錄由一個所有者(owner)和一個組(group)。文件或者目錄對其所有者、同組下的其他用戶,已經所有其他用戶分別有著不同的權限。對目錄而言,當列出目錄內容時需要具有r權限,當新增或者刪除目錄中子節點需要w權限。當訪問目錄的子節點時需要x權限。
每個訪問HDFS的用戶進程的標識分為兩個部分,分別是用戶名和組名列表。例如,當用戶進程訪問一個HDFS上的文件或目錄app時,HDFS都要對其進行權限檢查。
6.1 用戶身份
HDFS權限管理類似與UNIX的機制,文件用戶分為文件屬性主、文件組和其他用戶,權限分為讀、寫、執行。
6.2 超級用戶
超級用戶即運行NameNode進程的用戶。寬泛地講,如果你啟動了NameNode,你就是超級用戶。超級用戶可以干任何事情,因為超級用戶能夠通過所有的權限檢查。
7. HDFS缺點
- 訪問延遲:HDFS不太適合那些低延遲(數十毫秒)訪問的應用程序,HDFS的設計主要是為了用于大吞吐量的數據,這是以一定的延遲為代價的。
- 對大量小文件的處理:因為NameNode把文件系統的元數據放置在內存中,所以文件系統所能容納的文件數量時NameNode的內存大小
了讓HDFS能夠處理好小文件,建議使用以下方法:
1)利用SequenceFile、MapFile、Har等方式歸檔小文件。這個方法的原理就是把小文件進行歸檔管理,HBase就是基于此的。對于這種方法,如果想找回原來的小文件
內容,就必須得知道其與歸檔文件的映射關系。
2)橫向擴展。既然一個Hadoop集群能管理的小文件數量有限,那就把幾個Hadoop集群拖在一個虛擬服務器后面,形成一個大的Hadoop集群。Google就這么干
過。
3)多Master設計。這個作用顯而易見。正在研發中的GFS II要改為分布式多Master設計,還要支持Master的Failover,而且Block大小也要改為1M,要有意調優處
理小文件。
- 多用戶寫,任意文件修改:目前Hadoop只支持單用戶寫,不支持并發多用戶寫。可以使用Append操作在文件的末尾添加數據,但不支持在文件的任意位置進行修改。
總結
以上是生活随笔為你收集整理的Hadoop详解(二):HDFS存储系统设计原理的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Hadoop详解(三):HDFS完全分布
- 下一篇: Hadoop详解(四):HDFS she