HDFS的架構

簡單文字發表於2013-02-28

  HDFS(Hadoop Distributed File System)作為Hadoop下的一個子專案,是目前使用極為廣泛的分散式檔案系統。它的設計目的是提供一個高容錯,且能部署在廉價硬體的分散式系統;同時,它能支援高吞吐量,適合大規模資料集應用。這一目標可以看做是HDFS的架構目標。顯然,這樣的架構設計主要還是滿足系統的質量屬性,包括如何保證分散式儲存的可靠性,如何很好地支援硬體的水平擴充套件,如何支援對大資料處理的高效能以及客戶端請求的高吞吐量。所以,HDFS的架構設計頗有參考價值,在Hadoop的Apache官方網站上也給出了HDFS的架構指南。在The Architecture of Open Source Applications卷I的第8章也詳細介紹了HDFS的架構。

  HDFS的高層設計看起來很簡單,主要包含NameNode與DataNode,它們之間的通訊,包括客戶端與HDFS NameNode伺服器的通訊則基於TCP/IP。客戶端通過一個可配置的TCP埠連線到NameNode,通過ClientProtocol協議與NameNode互動。而DataNode使用DatanodeProtocol協議與NameNode互動。一個遠端過程呼叫(RPC)模型被抽象出來封裝ClientProtocol和Datanodeprotocol協議。

  通常,一個HDFS Cluter由一個NameNode和多個DataNode組成,且在大多數情況下,會由一臺專門的機器執行NameNode例項。下圖是HDFS的High Level Architecture:

HDFS的架構

本圖來自IBM DeveloperWorks

  注意,在這個架構圖中,觀察各節點之間的通訊,容易造成一個誤解是NameNode會直接與DataNode通訊。實則不然。雖然,NameNode可以看做是DataNode的管理者甚至是仲裁者,但由於DataNode的數量通常很多,且都是分散式部署在不同的機器上,若NameNode需要主動發起對各個DataNode的請求,會導致NameNode的負載過大,且對於網路的要求也極高。因此,在設計上,NameNode不會主動發起RPC,而是響應來自客戶端或Datanode的RPC請求。如果NameNode需要獲得指定DataNode的資訊,則是通過DataNode呼叫函式後的一個簡單返回值。每個DataNode都會維護一個開放的Socket,以支援客戶端程式碼或其他DataNode的讀寫請求。NameNode知道該Socket的Host與Port。

HDFS的架構

  一個好的架構必然遵循了好的架構原則。HDFS架構有許多值得我們借鑑或參考的設計決策,其中它所遵循的架構原則,對HDFS滿足架構目標起到了決定性的作用。這些原則包括:後設資料與資料分離;主/從架構;一次寫入多次讀取;移動計算比移動資料更划算。

  後設資料與資料分離

  這主要體現在NameNode與DataNode之分,這種分離是HDFS最關鍵的架構決策。這兩種節點的分離,意味著關注點的分離。對於一個檔案系統而言,檔案本身的屬性(即後設資料)與檔案所持有的資料屬於兩個不同的關注點。一個簡單的例子是檔名的更改。如果不實現分離,針對一個屬性的修改,就可能需要對資料塊進行操作,這是不合理的。如果不分離這兩種節點,也不利於檔案系統的分散式部署,因為我們很難找到一個主入口點。顯然,這一原則是與後面提到的主/從架構是一脈相承的。

  NameNode負責維護檔案系統的名字空間,任何對檔案系統名字空間或屬性的修改都將被NameNode記錄下來。NameNode會負責執行與檔案系統名稱空間的操作,包括開啟、關閉、重新命名檔案或目錄。它同時還要負責決定資料塊到DataNode的對映。從某種意義上講,NameNode是所有HDFS後設資料的仲裁者和資源庫。

  DataNode則負責響應檔案系統客戶端發出的讀寫請求,同時還將在NameNode的指導下負責執行資料庫的建立、刪除以及複製。

  因為所有的使用者資料都存放在DataNode中,而不會流過NameNode,就使得NameNode的負載變小,且更有利於為NameNode建立副本。

  主/從架構

  主從架構表現的是Component之間的關係,即由主元件控制從元件。在HDFS中,一個HDFS叢集是由一個NameNode和一定數目的DataNode組成。NameNode是一箇中心伺服器,負責管理檔案系統的名字空間(namespace)以及客戶端對檔案的訪問。叢集中的DataNode一般是一個節點一個,負責管理它所在節點上的儲存。

  一次寫入多次讀寫

  一次寫入多次讀寫,即Write Once Read Many,是HDFS針對檔案訪問採取的訪問模型。HDFS中的檔案只能寫一次,且在任何時間只能有一個Writer。當檔案被建立,接著寫入資料,最後,一旦檔案被關閉,就不能再修改。這種模型可以有效地保證資料一致性,且避免了複雜的併發同步處理,很好地支援了對資料訪問的高吞吐量。

  移動計算比移動資料更划算

  移動計算比移動資料更划算,即moving computation is cheaper than moving data。對於資料運算而言,越靠近資料,執行運算的效能就越好,尤其是當資料量非常大的時候,更是如此。由於分散式檔案系統的資料並不一定儲存在一臺機器上,就使得運算的資料常常與執行運算的位置不相同。如果直接去遠端訪問資料,可能需要發起多次網路請求,且傳輸資料的成本也相當客觀。因此最好的方式是保證資料與運算離得最近。這就帶來兩種不同的策略。一種是移動資料,另一種是移動運算。顯然,移動資料,尤其是大資料的成本非常之高。要讓網路的消耗最低,並提高系統的吞吐量,最佳方式是將運算的執行移到離它要處理的資料更近的地方,而不是移動資料。

  HDFS在改善吞吐量與資料訪問效能上還做出了一個好的設計決策,就是資料塊的Staging。當客戶端建立檔案時,並沒有立即將其傳送給NameNode,而是將檔案資料儲存到本地的臨時檔案中。這個操作是透明的,客戶端不會覺察,也不必關心。檔案的建立事實上是一個流資料的寫,當臨時檔案累計的資料量超過一個資料塊大小時,客戶端才會聯絡NameNode。NameNode將檔名插入檔案系統的層次結構中,並且分配一個資料塊給它。然後返回Datanode的識別符號和目標資料塊給客戶端。接著,客戶端將這塊資料從本地臨時檔案上傳到指定的Datanode上。當檔案關閉時,在臨時檔案中剩餘的沒有上傳的資料也會傳輸到指定的Datanode上。然後客戶端告訴Namenode檔案已經關閉。此時Namenode才將檔案建立操作提交到HDFS的檔案系統。這個操作的大致時序圖如下所示:

HDFS的架構

  採用這種客戶端快取的方式,可以有效地減少網路請求,避免大資料的寫入造成網路堵塞,進而提高網路吞吐量。

相關文章