1. 程式人生 > 實用技巧 >你的最後一篇 HDFS!

你的最後一篇 HDFS!

Hadoop

1. Hadoop 介紹

The Apache Hadoop project develops open-source software for reliable, scalable, distributed computing.
The Apache Hadoop software library is a framework that allows for the distributed processing of large data sets across clusters of computers using simple programming models. It is designed to scale up from single servers to thousands of machines, each offering local computation and storage. Rather than rely on hardware to deliver high-availability, the library itself is designed to detect and handle failures at the application layer, so delivering a highly-available service on top of a cluster of computers, each of which may be prone to failures.

Hadoop 是開源的可靠、可伸縮的分散式計算軟體。從單臺伺服器擴充套件到數千臺機器,每臺都能提供本地計算和儲存,通過簡單的程式設計模型跨計算機叢集對大型資料集進行分散式處理。與依賴硬體來提供高可用不用,Hadoop 本身的設計目的就是在每一臺伺服器都有可能發生故障的前提下設計完成的。

Hadoop 的開發過程主要經歷了 1.x、2.x 和 3.x,現在主流還是使用 2.x 和 3.x 居多,2.x 版本比 1.x 版本多了 Yarn 資源排程框架,3.x 版本在 2.x 版本的基礎上天生支援 HA(Hadoop 高可用)。

2. Hadoop 叢集配置

2.1 Hadoop 叢集安裝

初學者應該多關注 Hadoop Apache 官網,官網上有安裝及報錯資料。Hadoop 單節點偽分散式安裝介紹網址如下:

Hadoop 偽分散式安裝

初學者使用虛擬機器或者雲伺服器主機進行 Hadoop 偽分散式安裝即可。

2.2 Hadoop 配置

在完成 Hadoop 安裝之後,預設配置即可,但是有些引數依舊重要,我們要了解知道,為以後 Hadoop 叢集配置調優打下基礎。

  1. 日誌

    Hadoop 使用 Apache log4j 來記錄日誌,編輯 conf/log4j.properties 檔案可以改變 Hadoop 守護程序的日誌配置。

  2. 機架感知

    Hadoop 元件可識別機架。Hadoop 會將 HDFS 塊利用機架感知放置在不同的機架上,以此來進行容災和容錯。如果網路交換機叢集中發生故障,但是叢集存在分割槽,這將提供資料可用性。

    預設使用機架識別符號和主機 IP 來進行標識。同樣,如果我們有特殊需求可以進行定製化機架感知。

    Hadoop 官網關於機架感知介紹

2.3 執行程序

Hadoop 安裝啟動後使用 jps 命令可以看到有哪些啟動程序。

  1. NameNode

    是 HDFS 的主伺服器,管理檔案系統的目錄樹以及對叢集中儲存檔案的訪問,儲存有 metadate,不斷讀取記錄叢集中 DataNode 主機狀況和工作狀態。

  2. SecondaryNameNode

    NameNode 的冷備,負責週期性的合併 esimage 以及 editslog ,減少 NameNode 的工作量。

  3. DataNode

    負責管理各個儲存節點,每個儲存資料的節點都有一個 DataNode 守護程序。

  4. ResourceManager

    負責排程 DataManager 上的資源,每個 DataNode 都有一個 NodeManager (TaskTracker)來執行實際工作。

  5. NodeManager

    管理 slave 節點的資源。

3 Hadoop 架構設計

3.1 HDFS的設計

Hadoop 以流式資料訪問模式來儲存超大檔案,運行於商業硬體叢集上。

  1. 超大檔案

    "超大檔案"在這裡指具有幾百 MB,幾百 GB 甚至幾百 TB 大小的檔案。

  2. 流式資料訪問

    HDFS 的構建思路是這樣的:一次寫入、多次讀取是最高效的訪問模式,資料集通常由資料來源生成或從資料來源複製而來,接著長時間在此資料集上進行各種分析。每次分析都將涉及該資料集的大部分甚至全部,因此讀取整個資料集的時間延遲比讀取第一條記錄的時間延遲更重要。

  3. 商用硬體

    Hadoop 並不需要執行在昂貴且高可靠的硬體上,它是設計執行在商用硬體的叢集上,因此至少對於龐大的叢集來說,節點故障的概率還是非常高的。HDFS 遇到上述故障時,被設計成能夠繼續執行且不讓使用者察覺到明顯的中斷。

  4. 低時間延遲的資料訪問

    要求低時間延遲資料訪問的應用,例如幾十毫秒範圍,不適合在 HDFS 上執行,HDFS 是為高資料吞吐量應用優化的,這可能會以提高時間延遲為代價,對於低延遲的訪問需求,HBase 是更好的選擇。

  5. 大量的小檔案

    由於 namenode 將檔案系統的元資料儲存在記憶體中,因此該檔案系統所能儲存的檔案總數受限於 namenode 的記憶體總量。根據經驗,每個檔案、目錄和資料塊的儲存資訊大約佔 150 位元組。因此,距離來說,如果有一百萬個檔案,且每個檔案佔一個數據塊,那至少需要 300 MB 的記憶體。儘管儲存上百萬個檔案是可行的,但是儲存數十億個檔案就超出了當前硬體的能力。

  6. 多使用者寫入,任意修改檔案

    HDFS 中的檔案寫入只支援單個寫入者,而且寫操作總是以"只新增"方式在檔案末尾寫資料。它不支援多個寫入者的操作,也不支援在檔案的任意位置進行修改

3.2 HDFS 的概念

3.2.1 資料塊

和普通的檔案系統相同,HDFS 同樣也有(block)的概念,預設為 128 MB。HDFS 上的檔案也被劃分為塊大小的多個分塊(chunk),作為獨立的儲存單元。HDFS 中小於一個塊大小的檔案不會佔據整個塊的空間。

HDFS 中塊為什麼預設 128 MB

HDFS 中的塊預設為 128 MB,是為了最小化定址開銷。如果塊足夠大,從磁碟傳輸資料的時間會明顯大於定位這個塊開始位置所需的時間。因此傳輸一個由多個快組成的大檔案的時間取決於磁碟傳輸速率。

但是這個塊大小的引數也不能設定的過大,MapReduce 中的 map 任務通常一次只處理一個塊中的資料,因此如果任務數太少(少於叢集中的節點數量),作業的執行速度就會比較慢。

檔案分塊的好處

  1. 設計成分塊,那麼一個檔案的大小可以大於網路中任意一個磁碟的容量。檔案中的所有塊並不需要儲存在同一個磁碟上,分塊後可以利用叢集中任意一個機器進行儲存。
  2. 使用抽象塊而非整個檔案作為儲存單元,簡化了儲存子系統的設計,簡化了儲存管理,同時也消除了對元資料的顧慮(塊只要儲存的大塊檔案,而檔案的元資料,如許可權資訊,並不需要與塊一起儲存,這樣的話其他系統就可以單獨管理這些元資料)。
  3. 塊非常適用於資料備份進而提供資料容錯能力和提高可用性。HDFS 中每個塊的預設副本數為 3,使用機架感知,將這些塊分佈在不同的伺服器上,既能減少叢集中單個機器的讀取負載,又能進行容錯容災。

3.2.2 塊快取

通常 datanode 從磁碟讀取塊,但是對於訪問頻繁的檔案,其對應的塊可能被顯式的快取在 datanode 的記憶體中,以堆外記憶體(off-heap block cache)的形式存在。作業排程器(用於MapReduce、Spark和其他框架的)通過在快取塊的 datanode 上執行任務,可以利用塊快取的優勢提高讀操作的效能。例如,連線(join)操作中使用的一小的查詢表就是塊快取的很好的候選。

3.3 HDFS 檔案讀取

  1. 客戶端向 NameNode 發出寫檔案請求。
  2. 檢查是否已存在檔案、檢查許可權。若通過檢查,直接先將操作寫入EditLog,並返回輸出流物件。
    (注:WAL,write ahead log,先寫 Log,再寫記憶體,因為 EditLog 記錄的是最新的HDFS客戶端執行所有的寫操作。如果後續真實寫操作失敗了,由於在真實寫操作之前,操作就被寫入 EditLog 中了,故 EditLog 中仍會有記錄,我們不用擔心後續 client 讀不到相應的資料塊,因為在第 5 步中 DataNode 收到塊後會有一返回確認資訊,若沒寫成功,傳送端沒收到確認資訊,會一直重試,直到成功)
  3. client 端按 128 MB 的塊切分檔案。
  4. client 將 NameNode 返回的分配的可寫的 DataNode列表Data資料 一同傳送給最近的第一個 DataNode 節點,此後 client 端和 NameNode 分配的多個 DataNode 構成 pipeline 管道,client 端向輸出流物件中寫資料。client 每向第一個 DataNode 寫入一個packet,這個packet便會直接在 pipeline 裡傳給第二個、第三個…DataNode。
    (注:並不是寫好一個塊或一整個檔案後才向後分發)
  5. 每個 DataNode 寫完一個塊後,會返回確認資訊
    (注:並不是每寫完一個 packet 後就返回確認資訊,個人覺得因為 packet 中的每個 chunk 都攜帶校驗資訊,沒必要每寫一個就彙報一下,這樣效率太慢。正確的做法是寫完一個 block 塊後,對校驗資訊進行彙總分析,就能得出是否有塊寫錯的情況發生)
  6. 寫完資料,關閉輸輸出流。
  7. 傳送完成訊號給 NameNode。
    (注:傳送完成訊號的時機取決於叢集是強一致性還是最終一致性,強一致性則需要所有 DataNode 寫完後才向 NameNode 彙報。最終一致性則其中任意一個 DataNode 寫完後就能單獨向 NameNode 彙報,HDFS 一般情況下都是強調強一致性)

3.4 HDFS 檔案寫入

  1. client 訪問 NameNode ,查詢元資料資訊,獲得這個檔案的資料塊位置列表,返回輸入流物件。
  2. 就近挑選一臺 datanode 伺服器,請求建立輸入流 。
  3. DataNode 向輸入流中中寫資料,以 packet 為單位來校驗。
  4. 關閉輸入流

3.5 讀寫過程中保證資料完整性

HDFS 通過校驗和保證資料完整性。因為每個 chunk 中都有一個校驗位,一個個 chunk 構成 packet ,一個個 packet 最終形成 block ,故可在 block 上求校驗和。HDFS 的 client 端即實現了對 HDFS 檔案內容的校驗和(checksum)檢查。當客戶端建立一個新的 HDFS 檔案時候,分塊後會計算這個檔案每個資料塊的校驗和,此校驗和會以一個隱藏檔案形式儲存在同一個 HDFS 名稱空間下。當 client 端從HDFS 中讀取檔案內容後,它會檢查分塊時候計算出的校驗和(隱藏檔案裡)和讀取到的檔案塊中校驗和是否匹配,如果不匹配,客戶端可以選擇從其他 DataNode 獲取該資料塊的副本。