干貨,圖文詳解 HDFS 的工作機制及其原理
HDFS 是基于 流數據 訪問模式的 分布式 文件系統(HDFS放寬了一部分 POSIX約束 ,來實現 流式讀取 文件系統數據的目的),支持存儲 海量 的數據,可以運行在 低成本 的硬件上。其提供 高吞吐量 、高容錯性 的數據訪問,非常適合大規模數據集上的應用。了解 HDFS 的工作機制,可以加深我們對分布式系統的理解,以及增強遇到問題時的分析解決能力,以下介紹下 HDFS 的工作機制。
如果想了解 HDFS ,可以參考這篇文章:HDFS 及其組成框架介紹 。
一、 機架感知
機架感知的設計,考慮到兩個方面:
不同節點之間的通信,希望在同一機架內進行(Hadoop集群會分布在很多機架上),而不是跨機架;
為了提高 容錯 能力,NameNode (名稱節點)會盡可能把 數據塊的副本 放在多個機架上。
DataNode 的網絡拓撲圖如下:
如上圖,D1、R1是交換機,最底層是 DataNode 。可執行腳本文件返回各 DataNode 的機架 ID ,即 RackID(比如,H1 的 parent 是R1,R1的 parent 是D1,則 H1 的 RackID=/D1/R1/H1)。
有了這些 RackID 信息,就可以計算任意兩臺 DataNode 之間的距離了:
distance(/D1/R1/H1,/D1/R1/H1)=0 //相同的 DataNode distance(/D1/R1/H1,/D1/R1/H2)=2 //同一個 Rack 下不同的 DataNode distance(/D1/R1/H1,/D1/R1/H4)=4 //同一 IDC 下不同的 DataNode distance(/D1/R1/H1,/D2/R3/H7)=6 //不同 IDC 下的 DataNode
~IDC是互聯網數據中心,可以理解為機房。~
默認情況下,HDFS 不能 自動判斷 集群中各個 DataNode 的網絡拓撲情況,集群 默認都 處在同一個機架名為 /default-rack的機架上(在這種情況下,任何一臺 DataNode 機器,不管在物理上是否是屬于同一個機架,都會被認為是在同一個機架下)。
通常,我們通過 外在腳本 實現機架感知,需要配置 net.topology.script.file.name屬性(屬性值一般是一個可執行腳本文件的路徑)。腳本接收一個值,再輸出一個值(一般都是接收 IP地址 ,輸出這個地址所對應的 機架信息 )。
二、 副本冗余存儲策略
HDFS 上的文件對應的數據塊保存有多個副本(默認保存3個副本),且提供 容錯機制 ,副本 丟失 或 宕機(即 死機) 時自動恢復。
下面,以保存 3個副本 為例:
第一個副本(副本一):放置在 上傳文件 的數據節點上(若是在 集群外 提交,則隨機挑選一個 CPU比較空閑、磁盤不太滿 的節點)。
第二個副本(副本二):放置在與第一個副本 不同 的機架的節點上。
第三個副本(副本三):放置在與第二個副本 相同 機架的其他節點上。
如果有 更多 副本,那么這些副本 隨機選擇 節點存放。
需要注意的是,副本并不都是均勻分布在不同的機架上。
副本冗余存儲策略,主要有三個優點:
減少了機架間的 數據傳輸 ,提高了寫操作的效率。(不會影響數據的可靠性和可用性,因為機架的錯誤遠遠比節點的錯誤小)
減少了 讀取數據 時所需的網絡傳輸總帶寬。(因為數據塊只放在兩個不同的機架上)
在不損害數據 可靠性 和 讀取性能 的情況下,改進了寫操作的性能。(一個副本在一個機架的一個節點上,另外兩個副本在另一個機架的不同節點上,其他副本則 均勻分布 在剩下的機架中。如 2.1 所介紹。)
三、 文件傳輸過程
在 HDFS 中 讀寫數據 的過程都是通過數據流完成的。HDFS 提供了數據流的 I/O操作類(包括 FSDataInputStream 和 FSDataOutputStream )
HDFS 文件讀取(即 數據下載)過程如圖所示:
⑴ HDFS 客戶端通過 DistributeFileSystem 對象的 open() 方法打開需要讀取的文件。
⑵ DistributeFileSystem 向遠程的 NameNode 節點發起 RPC調用 ,得到文件的數據塊信息,返回數據塊列表。(對于每個數據塊,NameNode 返回該數據塊的 DataNode 地址)
⑶ DistributeFileSystem 返回一個 FSDataInputStream 對象給客戶端,客戶端調用 FSDataInputStream 對象的 read() 方法讀取數據。
⑷ 通過對數據流反復調用 read() 方法,把數據從數據節點傳輸到客戶端。
⑸ 當一個節點的數據讀取完畢時, DFSInputStream 對象會關閉與此數據節點的連接,然后連接此文件 下一個數據塊 的最近數據節點。
⑹ 當客戶端讀取完數據時,調用 FSDataInputStream 對象的 close() 方法關閉輸入流。
FSDataInputStream 輸入流類的常用方法:
pos 指定從輸入流中讀取數據的位置;offset 指定數據寫入緩沖區的位置(偏移量);len 指定讀操作的最大字節數。
HDFS 文件寫入(即 數據上傳)過程如圖所示:
⑴ 客戶端調用 DistributedFileSystem 對象的 create() 方法創建一個文件輸出流對象。
⑵ DistributedFileSystem 對象遠程的 NameNode 節點發起一次 RPC調用 ,NameNode 檢查這個文件 是否存在 ,以及客戶端 是否有權限 新建文件。
⑶ 客戶端調用 FSDataOutputStream 對象的 write() 方法寫數據(數據鮮卑寫入緩沖區,再被切分為一個個數據包)。
⑷ 每個數據包被發送到由 NameNode 節點分配的一組數據節點中的一個數據節點上,在這組數據節點組成的管道上依次傳輸數據包。
⑸ 管道上的節點按反向順序返回確認信息,最終由管道的第一個數據節點將整條管道的確認信息發送給客戶端。
⑹ 客戶端完成寫入,調用 close() 方法關閉文件輸出流。
⑺ 通知 NameNode 文件寫入成功。
FSDataOutputStream 輸入流類的常用方法:
len 指定讀操作的最大字節數。
四、 數據容錯
HDFS 能夠在出錯的情況下,保證 數據存儲 的可靠性。常見的出錯情況有 NameNode 節點出錯、DataNode 節點出錯 和 數據出錯 這三種情況。
HDFS 中所有元數據都保存在 NameNode (名稱節點)上,NameNode 節點維護 edits 和 fsimage 這兩個文件。(如果這兩個文件損壞,HDFS 就會 失效 )
Hadoop 提供了兩個機制,來確保 NameNode 的安全:
把 NameNode 節點上的元數據信息同步存儲到其他文件系統(比如 NFS ),當 NameNode 出現故障時,HDFS 自動切換到備用的 NameNode 上(HDFS HA ,就是采用共享存儲系統來存儲 edits 的)。
運行一個 SecondaryNameNode 節點,當 NameNode 宕機時,利用 SecondaryNameNode 的元數據信息進行系統恢復(仍然會有 部分數據 丟失)。
通常,這 兩個方法 結合使用。
NameNode 通過 心跳信號 來檢測近期不發送心跳信號的 DataNode,并將其標志為 宕機 (每個 DataNode 周期性地向 NameNode 發送心跳信號),不再發送 新的 I/O請求 給它們。
數據塊需要重新復制的情況:
某個 DataNode 節點丟失;
DataNode 上的硬盤出錯;
某個副本損壞;
某個數據塊的副本系數低于設定值。
從 DataNode 獲取的數據塊,有可能本身就是損壞的(比如可能是因為 網絡錯誤 、軟件bug 或者 DataNode的存儲設備錯誤)。
HDFS 使用 校驗和來判斷數據塊是否損壞。HDFS 的每個 DataNode 節點,保存了檢測校驗的日志(客戶端的每一次檢驗都會被記錄)。
BigData Pro 大數據 大數據
版權聲明:本文內容由網絡用戶投稿,版權歸原作者所有,本站不擁有其著作權,亦不承擔相應法律責任。如果您發現本站中有涉嫌抄襲或描述失實的內容,請聯系我們jiasou666@gmail.com 處理,核實后本網站將在24小時內刪除侵權內容。