大數據學習筆記(四)——分佈式文件系統HDFS

第四章 分佈式文件系統HDFS

4.1 分佈式文件系統

相對於傳統的本地文件系統而言,分佈式文件系統(Distributed File System)是一種通過網絡實現文件在多臺主機上進行分佈式存儲的文件系統,分佈式文件系統的設計一般採用“客戶端/服務器”(Client/Server)模式,客戶端以特定的通信協議通過網絡與服務器建立連接,提出文件訪問請求,客戶端和服務器可以通過設置訪問權來限制請求方對底層數據存儲塊的訪問。

4.1.1 計算機集羣結構

普通文件系統與分佈式文件系統的對比:

  • 普通文件系統只需要單個計算機節點就可以完成文件的存儲和處理,單個計算機節點由處理器、內存、高速緩存和本地磁盤構成;
  • 分佈式文件系統把文件分佈存儲到多個計算機節點上,成千上萬的計算機節點構成計算機集羣,與之前使用多個處理器和專用高級硬件的並行化處理裝置不同的是,目前的分佈式文件系統所採用的計算機集羣都是由普通硬件構成的,這就大大降低了硬件上的開銷。

計算機集羣的基本架構如下圖所示,集羣中的計算機節點存放在機架(Rack)上,每個機架可以存放8~64個計算機節點同一機架上的不同節點之間通過網絡互連(常採用吉比特以太網),多個不同機架之間採用另一級網絡或交換機互連
在這裏插入圖片描述

4.1.2 分佈式文件系統的結構

普通文件系統與分佈式文件系統的對比:

  • 普通文件系統一般會把磁盤空間劃分爲每512字節一組,稱爲“磁盤塊”,它是文件系統讀寫操作的最小單位,文件系統的(Block)通常是磁盤塊的整數倍,即每次讀寫的數據量必須是磁盤塊大小的整數倍;
  • 分佈式文件系統也採用了的概念,文件被分成若干個塊進行存儲,塊是數據讀寫的基本單元,只不過分佈式文件系統的塊要比普通文件系統中的塊大很多,比如,HDFS默認的一個塊的大小是64MB,而且與普通文件系統不同的是,在分佈式文件系統中,如果一個文件小於一個數據塊的大小,它並不佔用整個數據塊的存儲空間

分佈式文件系統在物理結構上是由計算機集羣中的多個節點構成的,如下圖所示,這些節點分爲兩類:一類叫“主節點”(Master Node),或者也被稱爲“名稱節點"(NameNode);另一類叫“從節點"(Slave Node),或者也被稱爲“數據節點"(DataNode):
在這裏插入圖片描述

  • 名稱節點負責文件和目錄的創建、刪除和重命名等,同時管理着數據節點和文件塊的映射關係,因此客戶端只有訪問名稱節點才能找到請求的文件塊所在的位置,進而到相應位置讀取所需文件塊;
  • 數據節點負責數據的存儲和讀取,在存儲時,由名稱節點分配存儲位置,然後由客戶端把數據直接寫入相應數據節點,在讀取時,客戶端從名稱節點獲得數據節點和文件塊的映射關係,然後就可以到相應位置訪問文件塊。數據節點也要根據名稱節點的命令創建、刪除數據塊和冗餘複製

計算機集羣中的節點可能發生故障,因此爲了保證數據的完整性,分佈式文件系統通常採用多副本存儲,文件塊會被複製爲多個副本,存儲在不同的節點上,而且存儲同一文件塊的不同副本的各個節點會分佈在不同的機架上,這樣在單個節點出現故障時,就可以快速調用副本重啓單個節點上的計算過程,而不用重啓整個計算過程,整個機架出現故障時也不會丟失所有文件塊。文件塊的大小和副本個數通常可以由用戶指定

分佈式文件系統是針對大規模數據存儲而設計的,主要用於處理大規模文件,如TB級文件,處理過小的文件不僅無法充分發揮其優勢,而且會嚴重影響到系統的擴展和性能

4.1.3 分佈式文件系統的設計需求

分佈式文件系統的設計目標主要包括透明性、併發控制、可伸縮性、容錯以及安全需求等,但是在具體實現中,不同產品實現的級別和方式都有所不同,下表給出了分佈式文件系統的設計需求及其具體含義,以及HDFS對這些指標的實現情況:

設計需求 含義 HDFS的實現情況
透明性 具備訪問透明性、位置透明性、性能和伸縮透明性。訪問透明性是指用戶不需要專門區分哪些是本地文件,哪些是遠程文件,用戶能夠通過相同的操作來訪問本地文件和遠程文件資源。位置透明性是指在不改變路徑名的前提下,不管文件副本數量和實際存儲位置發生何種變化,對用戶而言都是透明的,用戶不會感受到這種變化,只需要使用相同的路徑名就始終可以訪問同一個文件。性能和伸縮透明性是指系統中節點的增加或減少以及性能的變化對用戶而言是透明的,用戶感受不到什麼時候一個節點加入或退出了。 只能提供一定程度的訪問透明性,完全支持位置透明性、性能和伸縮透明性
併發控制 客戶端對於文件的讀寫不應該影響其他客戶端對同一個文件的讀寫 機制非常簡單,任何時間都只允許有一個程序寫入某個文件
文件複製 一個文件可以擁有在不同位置的多個副本 HDFS採用了多副本機制
硬件和操作系統的異構性 可以在不同的操作系統和計算機上實現同樣的客戶端和服務器端程序 採用Java語言開發,具有很好的跨平臺能力
可伸縮性 支持節點的動態加入或退出 建立在大規模廉價機器上的分佈式文件系統集羣,具有很好的可伸縮性
容錯 保證文件服務在客戶端或者服務端出現問題的時候能正常使用 具有多副本機制和故障自動檢測、恢復機制
安全 保障系統的安全性 安全性較弱

4.2 HDFS簡介

HDFS支持流數據讀取處理超大規模文件,並能夠運行在由廉價的普通機器組成的集羣上,這主要得益於HDFS在設計之初就充分考慮了實際應用環境的特點,那就是,硬件出錯在服務器集羣中是一種常態,而不是異常,因此,HDFS在設計上採取了多種機制保證在硬件出錯的環境中實現數據的完整性

總體而言,HDFS要實現以下目標:

  • 兼容廉價的硬件設備:在成百上千臺廉價服務器中存儲數據,常會出現節點失效的情況,因此HDFS設計了快速檢測硬件故障和進行自動恢復的機制,可以實現持續監視、錯誤檢查、容錯處理和自動恢復,從而使得在硬件出錯的情況下也能實現數據的完整性;
  • 流數據讀寫:普通文件系統主要用於隨機讀寫以及與用戶進行交互,而分佈式文件系統HDFS則是爲了滿足批量數據處理的要求而設計的,因此爲了提高數據吞吐率,HDFS放鬆了一些POSIX的要求,從而能夠以流式方式來訪問文件系統數據
  • 大數據集:HDFS中的文件通常可以達到GB甚至TB級別,一個數百臺機器組成的集羣裏面可以支持千萬級別這樣的文件;
  • 簡單的文件模型:HDFS採用了“一次寫入、多次讀取”的簡單文件模型,文件一旦完成寫入,關閉後就無法再次寫入,只能被讀取
  • 強大的跨平臺兼容性:HDFS是採用Java語言實現的,具有很好的跨平臺兼容性,支持JVM(Java Virtual Machine)的機器都可以運行HDFS。

HDFS特殊的設計,在實現上述優良特性的同時,也使得自身具有一些應用侷限性,主要包括以下幾個方面:

  • 不適合低延遲數據訪問:HDFS主要是面向大規模數據批量處理而設計的,採用流式數據讀取,具有很高的數據吞吐率,但是,這也意味着較高的延遲,因此,HDFS不適合用在需要較低延遲(如數十毫秒)的應用場合,對於低延遲要求的應用程序而言,HBase是一個更好的選擇;

  • 無法高效存儲大量小文件:小文件是指文件大小小於一個塊的文件,HDFS無法高效存儲和處理大量小文件,過多小文件會給系統擴展性和性能帶來諸多問題:

    ①HDFS採用名稱節點(NameNode)來管理文件系統的元數據,這些元數據被保存在內存中,從而使客戶端可以快速獲取文件實際存儲位置,通常,每個文件、目錄和塊大約佔150字節,如果有1000萬個文件,每個文件對應一個塊,那麼,名稱節點至少要消耗3GB的內存來保存這些元數據信息。很顯然,這時元數據檢索的效率就比較低了,需要花費較多的時間找到一個文件的實際存儲位置。而且,如果繼續擴展到數十億個文件時,名稱節點保存元數據所需要的內存空間就會大大增加,以現有的硬件水平,是無法在內存中保存如此大量的元數據的;

    ②用MapReduce處理大量小文件時,會產生過多的Map任務,線程管理開銷會大大增加,因此處理大量小文件的速度遠遠低於處理同等大小的大文件的速度;

    ③訪問大量小文件的速度遠遠低於訪問幾個大文件的速度,因爲訪問大量小文件,需要不斷從一個數據節點跳到另一個數據節點,嚴重影響性能。

  • 不支持多用戶寫入及任意修改文件:HDFS只允許一個文件有一個寫入者,不允許多個用戶對同一個文件執行寫操作,而且只允許對文件執行追加操作,不能執行隨機寫操作。

4.3 HDFS的相關概念

4.3.1 塊

在普通文件系統中,爲了提高磁盤讀寫效率,一般以數據塊爲單位,而不是以字節爲單位。比如,機械式硬盤(磁盤的一種)包含了磁頭和轉動部件,在讀取數據時有一個尋道的過程,通過轉動盤片和移動磁頭的位置,來找到數據在機械式硬盤中的存儲位置,然後才能進行讀寫。在IO開銷中,機械式硬盤的尋址時間是最耗時的部分,一旦找到第一條記錄,剩下的順序讀取效率是非常高的。因此,以塊爲單位讀寫數據,可以把磁盤尋道時間分攤到大量數據中

分佈式文件HDFS也同樣採用了塊的概念,默認的一個塊大小是64MB,在HDFS中的文件會被拆分成多個塊,每個塊作爲獨立的單元進行存儲。普通文件系統的塊一般只有幾千字節(byte),而HDFS在塊的大小的設計上要遠遠大於普通文件系統,HDFS這麼做的原因,是爲了最小化尋址開銷

HDFS尋址開銷不僅包括磁盤尋道開銷,還包括數據塊的定位開銷。當客戶端需要訪問一個文件時,首先從名稱節點獲得組成這個文件的數據塊的位置列表,然後根據位置列表獲取實際存儲各個數據塊的數據節點的位置,最後數據節點根據數據塊信息在本地Linux文件系統中找到對應的文件,並把數據返回給客戶端。設計一個比較大的塊,可以把上述尋址開銷分攤到較多的數據中,降低了單位數據的尋址開銷。因此,HDFS在文件塊大小設置上要遠遠大於普通文件系統,以期在處理大規模文件時能夠獲得更好的性能。當然,塊的大小也不宜設置過大,因爲,通常MapReduce中的Map任務一次只處理一個塊中的數據,如果啓動的任務太少,就會降低作業並行處理速度。

HDFS採用抽象的塊概念可以帶來以下幾個明顯的好處:

  • 支持大規模文件存儲:文件以塊爲單位進行存儲,一個大規模文件可以被分拆成若干個文件塊,不同的文件塊可以被分發到不同的節點上,因此一個文件的大小不會受到單個節點的存儲容量的限制,可以遠遠大於網絡中任意節點的存儲容量;
  • 簡化系統設計:首先,大大簡化了存儲管理,因爲文件塊大小是固定的,這樣就可以很容易計算出一個節點可以存儲多少文件塊;其次,方便了元數據的管理,元數據不需要和文件塊一起存儲,可以由其他系統負責管理元數據;
  • 適合數據備份:每個文件塊都可以冗餘存儲到多個節點上,大大提高了系統的容錯性和可用性。

4.3.2 名稱節點

在HDFS中,名稱節點(NameNode)負責管理分佈式文件系統的命名空間(Namespace),保存了兩個核心的數據結構,即FsImage和EditLog:

  • FsImage用於維護文件系統樹以及文件樹中所有的文件和目錄的元數據,FsImage文件包含文件系統中所有文件和目錄inode的序列化形式,每個inode是一個文件或目錄的元數據的內部表示。對於文件,存儲文件的複製等級、修改和訪問時間、訪問權限、塊大小以及組成文件的塊;對於目錄,則存儲目錄的修改時間、權限和配額元數據。FsImage文件沒有記錄文件包含的每個塊存儲在哪個數據節點,而是由名稱節點把這些映射信息保留在內存中,當數據節點加入HDFS集羣時,數據節點會把自己所包含的塊列表告知給名稱節點,此後會定期執行這種告知操作,以確保名稱節點的塊映射是最新的;
  • 操作日誌文件EditLog中記錄了所有針對文件的創建、刪除、重命名等操作。
    在這裏插入圖片描述

名稱節點記錄了每個文件中各個塊所在的數據節點的位置信息,但是並不持久化存儲這些信息,而是在系統每次啓動時掃描所有數據節點重構得到這些信息

名稱節點在啓動時,會將FsImage的內容加載到內存當中,然後執行EditLog文件中的各項操作,使得內存中的元數據和實際保持同步,這個操作完成以後,就會重新創建一個記錄最新元數據信息的FsImage文件,以及一個空的EditLog文件。

名稱節點在啓動的過程中處於“安全模式”,只能對外提供讀操作,無法提供寫操作。啓動過程結束後,系統就會退出安全模式,進入正常運行狀態,對外提供讀寫操作。

名稱節點啓動成功並進入正常運行狀態以後,HDFS中的更新操作都會被寫入到EditLog,而不是直接寫入FsImage,這是因爲對於分佈式文件系統而言,FsImage文件通常都很龐大(一般都是GB級別以上), 如果所有的更新操作都直接往FsImage文件中添加,那麼系統就會變得非常緩慢,相對而言, EditLog通常都要遠遠小於FsImage,更新操作寫入到EditLog是非常高效的。

4.3.3 第二名稱節點

在名稱節點運行期間,HDFS 會不斷髮生更新操作,這些更新操作都是直接被寫入到EditLog文件,所以EditLog文件也會逐漸變大,在名稱節點運行期間,不斷變大的EditLog文件通常對於系統性能不會產生顯著影響,但是當名稱節點重啓時,需要將FsImage加載到內存中,然後逐條執行EditLog中的記錄,使得FsImage保持最新,因此,如果EditLog很大,就會導致整個過程變得非常緩慢,使得名稱節點在啓動過程中長期處於“安全模式”,無法正常對外提供寫操作,影響了用戶的使用。

爲了有效解決EditLog逐漸變大帶來的問題,HDFS在設計中採用了第二名稱節點(SecondaryNameNode),第二名稱節點是HDFS架構的一個重要組成部分,它的工作情況如下:
在這裏插入圖片描述

  1. SecondaryNameNode會定期和NameNode通信,請求其停止使用EditLog文件,暫時將新的寫操作寫到一個新的文件EditLog.new上來,這個操作是瞬間完成,上層寫日誌的函數完全感覺不到差別;
  2. SecondaryNameNode通過HTTP GET方式從NameNode上獲取到FsImage和EditLog文件,並下載到本地的相應目錄下;
  3. SecondaryNameNode將下載下來的FsImage載入到內存,然後一條一條地執行EditLog文件中的各項更新操作,使得內存中的FsImage保持最新,這個過程就是EditLog和FsImage文件合併;
  4. SecondaryNameNode執行完上一步操作之後,會通過post方式將新的FsImage文件發送到NameNode節點上;
  5. NameNode將從SecondaryNameNode接收到的新的FsImage替換舊的FsImage文件,同時將EditLog.new替換EditLog文件,通過這個過程EditLog就變小了。

由上述工作過程可以看到,第二名稱節點具有兩個方面的功能:

  • 可以完成EditLog與FsImage的合併操作,減小EditLog文件大小,縮短名稱節點重啓時間;
  • 可以作爲名稱節點的“檢查點”,保存名稱節點中的元數據信息。

4.3.4 數據節點

數據節點是分佈式文件系統HDFS的工作節點,負責數據的存儲和讀取,會根據客戶端或者是名稱節點的調度來進行數據的存儲和檢索,並且向名稱節點定期發送自己所存儲的塊的列表。

每個數據節點中的數據會被保存在各自節點的本地Linux文件系統中

4.4 HDFS體系結構

4.4.1 概述

HDFS採用了主從(Master/Slave)結構模型,一個HDFS集羣包括一個名稱節點(NameNode)和若干個數據節點(DataNode),名稱節點作爲中心服務器,負責管理文件系統的命名空間及客戶端對文件的訪問,集羣中的數據節點一般是一個節點運行一個數據節點進程,負責處理文件系統客戶端的讀/寫請求,在名稱節點的統一調度下進行數據塊的創建、刪除和複製等操作。每個數據節點會週期性地向名稱節點發送“心跳"信息,報告自己的狀態,沒有按時發送心跳信息的數據節點會被標記爲“宕機”,不會再給它分配任何I/O請求。

用戶在使用HDFS時,仍然可以像在普通文件系統中那樣,使用文件名去存儲和訪問文件。實際上,在系統內部,一個文件會被切分成若干個數據塊,這些數據塊被分佈存儲到若干個數據節點上。當客戶端需要訪問一個文件時,首先把文件名發送給名稱節點,名稱節點根據文件名找到對應的數據塊(一個文件可能包括多個數據塊),再根據每個數據塊信息找到實際存儲各個數據塊的數據節點的位置,並把數據節點位置發送給客戶端,最後客戶端直接訪問這些數據節點獲取數據。在整個訪問過程中,名稱節點並不參與數據的傳輸。這種設計方式,使得個文件的數據能夠在不同的數據節點上實現併發訪問,大大提高了數據訪問速度。
在這裏插入圖片描述

HDFS採用Java語言開發,因此任何支持JVM的機器都可以部署名稱節點和數據節點。在實際部署時,通常在集羣中選擇一臺性能較好的機器作爲名稱節點,其他機器作爲數據節點。當然,一臺機器可以運行任意多個數據節點,甚至名稱節點和數據節點也可以放在一臺機器上行,不過,很少在正式部署中採用這種模式。HDFS集羣中只有唯一個名稱節點,該節點負責所有元數據的管理,這種設計大大簡化了分佈式文件系統的結構,可以保證數據不會脫離名稱節點的控制,同時,用戶數據也永遠不會經過名稱節點,這大大減輕了中心服務器的負擔,方便了數據管理。

4.4.2 HDFS命名空間管理

HDFS的命名空間包含目錄、文件和塊命名空間管理是指命名空間支持對HDFS中的目錄、文件和塊做類似普通文件系統的創建、修改、刪除等基本操作。在當前的HDFS體系結構中,在整個HDFS集羣中只有一個命名空間,並且只有唯一個名稱節點, 該節點負責對這個命名空間進行管理。

HDFS使用的是傳統的分級文件體系,因此用戶可以像使用普通文件系統一樣,創建、刪除目錄和文件,在目錄間轉移文件、重命名文件等。但是,HDFS還沒有實現磁盤配額和文件訪問權限等功能,也不支持文件的硬連接和軟連接(快捷方式)

4.4.3 通信協議

HDFS是一個部署在集羣上的分佈式文件系統,因此很多數據需要通過網絡進行傳輸。所有的HDFS通信協議都是構建在TCP/IP協議基礎之上的客戶端通過一個可配置的端口向名稱節點主動發起TCP連接,並使用客戶端協議與名稱節點進行交互名稱節點和數據節點之間則使用數據節點協議進行交互客戶端與數據節點的交互是通過RPC(Remote Procedure Call)來實現的。在設計上,名稱節點不會主動發起RPC,而是響應來自客戶端和數據節點的RPC請求

4.4.4 客戶端

客戶端是用戶操作HDFS最常用的方式,HDFS在部署時都提供了客戶端,HDFS客戶端是一個庫,暴露了HDFS文件系統接口,這些接口隱藏了HDFS實現中的大部分複雜性。嚴格來說,客戶端並不算是HDFS的一部分。客戶端可以支持打開、讀取、寫入等常見的操作,並且提供了類似Shell的命令行方式來訪問HDFS中的數據,此外,HDFS也提供了Java API,作爲應用程序訪問文件系統的客戶端編程接口

4.4.5 HDFS體系結構的侷限性

HDFS只設置唯一一個名稱節點,這樣做雖然大大簡化了系統設計,但也帶來了一些明顯的侷限性,具體如下:

  • 命名空間的限制:名稱節點是保存在內存中的,因此,名稱節點能夠容納的對象(文件、塊)的個數會受到內存空間大小的限制;
  • 性能的瓶頸:整個分佈式文件系統的吞吐量,受限於單個名稱節點的吞吐量;
  • 隔離問題:由於集羣中只有一個名稱節點,只有一個命名空間,因此,無法對不同應用程序進行隔離;
  • 集羣的可用性:一旦這個唯一的名稱節點發生故障,會導致整個集羣變得不可用。

4.5 HDFS的存儲原理

4.5.1 數據的冗餘存儲

作爲一個分佈式文件系統,爲了保證系統的容錯性和可用性,HDFS採用了多副本方式對數據進行冗餘存儲,通常一個數據塊的多個副本會被分佈到不同的數據節點上,如下圖所示:
在這裏插入圖片描述

多副本存儲方式有以下三個優點:

  • 加快數據傳輸速度:當多個客戶端需要同時訪問同一個文件時,可以讓各個客戶端分別從不同的數據塊副本中讀取數據,這就大大加快了數據傳輸速度;
  • 容易檢查數據錯誤:HDFS的數據節點之間通過網絡傳輸數據,採用多個副本可以很容易判斷數據傳輸是否出錯;
  • 保證數據的可靠性:即使某個數據節點出現故障失效,也不會造成數據丟失。

4.5.2 數據存儲策略

4.5.2.1 數據存放

爲了提高數據的可靠性與系統的可用性,以及充分利用網絡帶寬,HDFS採用了以機架(Rack)爲基礎的數據存放策略,一個HDFS集羣通常包含多個機架,不同機架之間的數據通信需要經過交換機或者路由器,同個機架中不同機器之間的通信則不需要經過交換機和路由器,這意味着同一個機架中不同機器之間的通信要比不同機架之間機器的通信帶寬大。

HDFS默認每個數據節點都是在不同的機架上,這種方法會存在一個缺點,那就是寫入數據的時候不能充分利用同一機架內部機器之間的帶寬,但是,與這點缺點相比,這種方法也帶來了更多很顯著的優點:

  • 可以獲得很高的數據可靠性,即使一個機架發生故障,位於其他機架上的數據副本仍然是可用的;
  • 在讀取數據的時候,可以在多個機架上並行讀取數據,大大提高了數據讀取速度
  • 可以更容易地實現系統內部負載均衡和錯誤處理

HDFS默認的冗餘複製因子是3,每一個文件塊會被同時保存到3個地方,其中有兩份副本放在同一個機架的不同機器上面,第三個副本放在不同機架的機器上面,這樣既可以保證機架發生異常時的數據恢復,也可以提高數據讀寫性能,一般而言,HDFS副本的放置策略如下:
在這裏插入圖片描述

  • 如果是在集羣內發起寫操作請求,則把第一個副本放置在發起寫操作請求的數據節點上,實現就近寫入數據,如果是來自集羣外部的寫操作請求,則從集羣內部挑選一臺磁盤不太滿、CPU不太忙的數據節點,作爲第一個副本的存放地;
  • 第二個副本會被放置在與第一個副本不同的機架的數據節點上;
  • 第三個副本會被放置在與第一個副本相同的機架的其他節點上;
  • 如果還有更多的副本,則繼續從集羣中隨機選擇數據節點進行存放。

4.5.2.2 數據讀取

HDFS提供了一個API可以確定一個數據節點所屬的機架ID,客戶端也可以調用API獲取自己所屬的機架ID。當客戶端讀取數據時,從名稱節點獲得數據塊不同副本的存放位置列表,列表中包含了副本所在的數據節點,可以調用API來確定客戶端和這些數據節點所屬的機架ID,當發現某個數據塊副本對應的機架ID和客戶端對應的機架ID相同時,就優先選擇該副本讀取數據,如果沒有發現,就隨機選擇一個副本讀取數據。

4.5.2.3 數據複製

HDFS的數據複製採用了流水線複製的策略,大大提高了數據複製過程的效率。當客戶端要往HDFS中寫入一個文件時,這個文件會首先被寫入本地,並被切分成若干個塊,每個塊的大小是由HDFS的設定值來決定的。每個塊都向HDFS集羣中的名稱節點發起寫請求,名稱節點會根據系統中各個數據節點的使用情況,選擇一個數據節點列表返回給客戶端,然後客戶端就把數據首先寫入列表中的第一個數據節點,同時把列表傳給第一個數據節點,當第一個數據節點接收到一個塊的數據的時候,將其寫入本地,並且向列表中的第二個數據節點發起連接請求,把自己已經接收到的數據和列表傳給第二個數據節點,當第二個數據節點接收到數據的時候,將其寫入本地,並且向列表中的第三個數據節點發起連接請求,依次類推,列表中的多個數據節點形成一條數據複製的流水線,最後,當文件寫完的時候,數據複製也同時完成

4.5.3 數據錯誤與恢復

HDFS具有較高的容錯性,可以兼容廉價的硬件,它把硬件出錯看作一種常態,而不是異常,並設計了相應的機制檢測數據錯誤和進行自動恢復,主要包括以下幾種情形:

  • 名稱節點出錯:名稱節點保存了所有的元數據信息,其中,最核心的兩大數據結構是FsImageEditlog,如果這兩個文件發生損壞,那麼整個HDFS文件系統將失效。HDFS採用兩種機制來確保名稱節點的安全:第一,把名稱節點上的元數據信息同步存儲到其他文件系統(比如遠程掛載的網絡文件系統NFS)中;第二,運行一個第二名稱節點,當名稱節點宕機以後,可以把第二名稱節點作爲一種彌補措施,利用第二名稱節點中的元數據信息進行系統恢復。一般會把上述兩種方式結合使用,當名稱節點發生宕機時,首先到遠程掛載的網絡文件系統中獲取備份的元數據信息,放到第二名稱節點上進行恢復,並把第二名稱節點作爲名稱節點來使用;

  • 數據節點出錯:每個數據節點會定期向名稱節點發送“心跳”信息,向名稱節點報告自己的狀態。當數據節點發生故障,或者網絡發生斷網時,名稱節點就無法收到來自一些數據節點的心跳信息,這時,這些數據節點就會被標記爲“宕機”,節點上面的所有數據都會被標記爲“不可讀”,名稱節點不會再給它們發送任何I/O請求。這時,有可能出現一種情形,即由於一些數據節點的不可用,會導致一些數據塊的副本數量小於冗餘因子。名稱節點會定期檢查這種情況,一旦發現某個數據塊的副本數量小於冗餘因子,就會啓動數據冗餘複製,爲它生成新的副本。HDFS和其它分佈式文件系統的最大區別就是可以調整冗餘數據的位置

  • 數據出錯:網絡傳輸和磁盤錯誤等因素,都會造成數據錯誤。客戶端在讀取到數據後,會採用md5和sha1對數據塊進行校驗,以確定讀取到正確的數據。在文件被創建時,客戶端就會對每一個文件塊進行信息摘錄,並把這些信息寫入到同一個路徑的隱藏文件裏面。當客戶端讀取文件的時候,會先讀取該信息文件,然後,利用該信息文件對每個讀取的數據塊進行校驗,如果校驗出錯,客戶端就會請求到另外一個數據節點讀取該文件塊,並且向名稱節點報告這個文件塊有錯誤,名稱節點會定期檢查並且重新複製這個塊。

4.6 HDFS的數據讀寫過程

HDFS的讀取數據過程請參照:HDFS的讀取數據過程詳解 + Java代碼實現

HDFS的寫入數據過程請參照:HDFS的寫入數據過程詳解 + Java代碼實現

4.7 HDFS操作常用Shell命令

請在僞分佈式或分佈式模式配置下的Hadoop上使用Shell命令操作HDFS,Hadoop的僞分佈式模式配置請參照:Linux系統Hadoop僞分佈式模式配置

HDFS支持很多Shell命令,例如hadoop fshdfs dfs都是HDFS最常用的Shell命令,兩者功能和用法相同,都可以查看HDFS文件系統的目錄結構、上傳和下載數據、創建文件等。

我們先來看一看如何查看命令的使用方法,打開Linux終端,啓動Hadoop:

start-dfs.sh

通過執行以下命令查看hadoop fshdfs dfs命令支持哪些操作:

hadoop fs

hdfs dfs

它們的執行結果相同,如下(這裏只列出部分輸出):
在這裏插入圖片描述
可以查看某個命令的具體用法,比如可以通過以下命令查看put命令的用法:

hdfs dfs -help put

hadoop fs -help put

輸出結果如下:
在這裏插入圖片描述
HDFS操作的一些常用Shell命令請參照:Linux系統HDFS操作常用Shell命令

4.8 HDFS的Web管理界面

在配置好Hadoop集羣之後,可以通過瀏覽器登錄"htp://[NameNodeIP]:50070”訪問HDFS文件系統,其中,[NameNodeIP]表示名稱節點的IP地址,例如,我們在本地機器上完成Hadoop僞分佈式安裝後,可以登錄http://localhost:50070來查看文件系統信息,如下:
在這裏插入圖片描述
通過該Web界面,我們可以查看當前文件系統中各個節點的分佈信息,瀏覽名稱節點上的存儲、登錄等日誌,以及下載某個數據節點上某個文件的內容。該Web界面的所有功能都能通過Hadoop提供的Shell命令或者Java API來等價實現

4.9 HDFS編程實踐

4.9.1 HDFS常用Java API

Hadoop採用Java語言開發,提供了Java API與HDFS進行交互,HDFS的Shell命令,在執行時實際上會被系統轉換成Java API進行調用

Hadoop官方網站提供了完整的Hadoop API文檔:http://hadoop.apache.org/docs/stable/api/,想要深入學習Hadoop編程,可以訪問Hadoop官網查看各個API的功能和用法,在這裏只介紹一些常用的Java API:

Java API 介紹
org.apache.hadoop.fs.FileSystem 一個通用文件系統的抽象基類,可以被分佈式文件系統繼承。所有可能使用Hadoop文件系統的代碼都要使用到這個類。Hadoop爲FileSystem這個抽象類提供了多種具體的實現,如LocalFileSystem 、DistributedFileSystem 、HftpFileSystem 、HsftpFileSystem、HarFileSystem 、KosmosFileSystem 、FtpFileSystem, NativeS3FileSystem
org.apache.hadoop.fs.FileStatus 一個接口,用於向客戶端展示系統中文件和目錄的元數據,具體包括文件大小、塊大小、副本信息、所有者、修改時間等,可通過FileSystem.listStatus()方法獲得具體的實例對象
org.apache.hadoop.fs.FSDataInputStream 文件輸入流,用於讀取Hadoop文件
org.apache.hadoop.fs.FSDataOutputStream 文件輸出流,用於寫Hadoop文件
org.apache.hadoop.conf.Configuration 訪問配置項,但是如果配置項的值,在core-site.xml中有對應的配置,則以core-site.xml爲準
org.apache.hadoop.fs.Path 用於表示Hadoop文件系統中的一個文件或者一個目錄的路徑
org.apache.hadoop.fs.PathFilter 一個接口, 通過實現方法PathFilter.accept(Path path)來判定是否接收路徑path表示的文件或目錄

4.9.2 編寫Java應用程序的準備工作

因爲Hadoop採用Java語言開發,所以我們首先要在Linux系統上安裝Java環境,具體步驟請參照:Linux系統安裝Java環境

在Linux系統上安裝Java環境成功以後,我們使用軟件Eclipse編寫Java程序,我們需要在Linux系統上安裝Eclipse,具體步驟請參照:Linux系統安裝Eclipse

在Linux系統上安裝Eclipse成功以後,就是一系列常規操作,打開Eclipse,創建一個項目等等,同學們應該對它比較熟悉了,具體用法網上一大把,就不多贅述了,在這裏介紹一下如何爲我們的項目添加需要的JAR包,這些JAR包中包含了可以訪問HDFS的Java API。

在添加JAR包之前,我們可以新建一個Library來管理我們要添加的JAR包,因爲我們需要添加的JAR包比較多,直接添加會顯得比較混亂,具體步驟請參照:Eclipse技巧——通過Library管理自己的JAR包

我們需要添加的JAR包都位於Hadoop的安裝目錄下,找到自己Hadoop的安裝目錄,我的安裝目錄是/usr/local/hadoop/,所以我需要添加的JAR包都位於/usr/local/hadoop//share/hadoop/目錄下,該目錄的內容如下:
在這裏插入圖片描述
爲了編寫能夠與HDFS交互的Java應用程序,一般需要向項目中添加以下JAR包:

  • /usr/local/hadoop//share/hadoop/common/目錄下的hadoop-common-2.7.7.jarhadoop-nfs-2.7.7.jar
  • /usr/local/hadoop//share/hadoop/common/lib/目錄下的所有JAR包
  • /usr/local/hadoop//share/hadoop/hdfs/目錄下的hadoop-hdfs-2.7.7.jarhadoop-hdfs-nfs-2.7.7.jar
  • /usr/local/hadoop//share/hadoop/hdfs/lib/目錄下的所有JAR包

4.9.3 編寫Java應用程序

在學習完HDFS的結構、原理以及功能後,Java代碼實現相關操作也必不可少,因爲這樣可以幫助我們加深理解,這裏列出一些Java代碼對HDFS相關操作的具體實現:

HDFS的寫入數據過程詳解 + Java代碼實現

HDFS的讀取數據過程詳解 + Java代碼實現

HDFS判斷文件或目錄是否存在——Shell命令實現 + Java代碼實現

需要注意的是,在上述Java代碼對HDFS相關操作的具體實現中,關於配置項的加載,可以不採用set()傳參方法進行配置,我們可以放置配置文件到當前工程下面,即把集羣上的配置文件core-site.xml和hdfs-site.xml拷貝一份放到當前工程項目下也就是Eclipse工作目錄的bin文件夾下面,這樣可以避免每次編寫Java代碼時都需要進行配置,可以這樣做是因爲在創建Configuration對象時會自動加載當前工程下的配置文件。

關於配置文件core-site.xml和hdfs-site.xml的具體配置請參照:Linux系統Hadoop僞分佈式模式配置

4.9.4 Java應用程序在Hadoop平臺上的部署

我們在編寫Java應用程序後,可以直接在Eclipse上編譯運行,也可以通過生成JAR包的方式把它部署到Hadoop平臺上運行,生成Java應用程序的JAR包的具體步驟請參照:Eclipse技巧——生成自己的JAR包,不過需要注意的是,我們新建的用來存放JAR包的文件夾應該位於Hadoop安裝目錄下。

在生成JAR包後,我們可以直接打開Linux終端,通過下列命令在Hadoop平臺上運行已經部署好的程序:

  1. 啓動Hadoop:
    start-dfs.sh 
    
  2. 進入JAR包所在目錄:
    cd JAR包所在目錄 
    
  3. 使用hadoop jar命令運行程序:
    hadoop jar JAR包名稱.jar 
    

4.10 學習資源

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章