Hadoop HDFS 設計隨想

珍惜時間,時間要花在作有用的事情上,力戒無心義的舉動node

——富蘭克林shell

引言

當數據的大小大於一臺獨立的電腦的存儲能力時,就有必要對它進行分區而且存儲在多臺單獨的電腦上。要將很是大的數據集合存儲在多臺電腦上,就會涉及到多臺電腦共享的文件系統,也就是分佈式文件系統。apache

分佈式文件系統(distributed file system) 是指管理網絡中跨多臺計算機存儲的文件系統。緩存

分佈式文件系統既然跨多臺電腦,經過網絡將它們互聯起來,就可能會出現其中的一個電腦節點鏈接中斷或者宕機的狀況,也就是節點故障。在這種狀況下也不能出現丟失整個文件系統任何數據的狀況,怎麼來作到呢?先讓咱們用發散思惟的方式來思考一下。網絡

  1. 將文件系統的每份數據備份,而且備份不能在同一臺物理計算器上,這樣能保證即便其中一臺計算機宕機,文件系統的總體數據仍是完整的
  2. 文件系統中的數據和文件信息(元信息)是兩個不一樣的東西,是否要將它們分佈在不一樣的地方?怎麼能保證文件信息(元信息)的穩定性,在一臺計算機宕機後,元信息不丟失,是否也要引入備份節點的概念?
  3. 既然文件的數據都比較大,它們的區塊該如何設計?每一個區塊是否應該設置的更大一點?
  4. 若是文件系統信息與文件數據分離,假如存儲文件系統信息的節點宕機該怎麼辦,如何確保分佈式文件系統的高可用性?

這些發散性問題正是 HDFS 設計時要解決的問題,下面就讓咱們一塊兒帶着這些問題來看下 HDFS 的解決方案。架構

HDFS 數據塊的設計

HDFS 是專門爲大數據場合設計的分佈式文件系統,要理解 HDFS 數據塊的設計,先要理解大數據場合下超大文件的特色。所謂超大文件是指具備幾百 MB,幾百 GB甚至幾百 TB 大小的文件。這類文件在大數據中佔有的比重是很是大的。HDFS 數據塊則主要是針對這些超大文件而設計的。maven

數據塊應該設置成多大?

HDFS 中默認的塊(block) 大小爲 128M,爲何設計的這麼大呢?分佈式

咱們知道讀取文件時主要有兩個時間開銷:ide

  • 磁盤傳輸時間
  • 定位磁盤塊的時間

若是塊很小的話,一個文件會有不少磁盤塊組成,光定位磁盤塊就會耗費不少時間。若是將塊的大小設置成 128M,定位磁盤塊就花不了太多時間,主要的時間會花費在傳輸數據上,這樣就很大程度節省了讀取時間。

固然,也不能設計成過大,MapReduce 中的map 任務一般一次只能處理一個塊的時間,任務數太少,做業運行的時間就比較慢了。

抽象成數據塊有哪些好處?

  1. 一個文件理論上能夠無限大

    一個文件能夠由任意個數據塊組成,並且這些數據塊不須要存儲在同一塊磁盤上,由此能夠推斷出,一個文件佔滿整個 Hadoop 集羣的整個磁盤空間。

  2. 文件數據與文件元信息分離,簡化系統設計

  3. 適合數據備份,從而提升數據容錯能力和可用性

    爲了保證數據的高可用性,默認會將每一個數據塊複製到 3 臺機器上,這樣即便其中一臺機器宕機,數據也不會丟失。

    當一臺機器宕機後,就會從其餘機器上讀取數據,而且採起必定的步驟將宕機的機器丟失的數據塊複製到其餘的機器上,從而保證副本的數量。

操做塊信息的命令

fsck 命令能夠顯示塊信息,如列出文件系統中各個文件由哪些塊組成的命令

hdfs fsck / -files -blocks

要獲取完整的 hdfs 命令列表,可參考 這裏

HDFS 中節點的設計

有幾種節點類型?

從上節中,咱們就看出 HDFS 的文件數據和文件元信息是分離的。由此,HDFS 集羣中的節點會分紅兩種類型:

  • namenode 管理節點
    • 對整個文件系統進行管理
    • 維護文件系統樹以及其中全部的文件和目錄
    • 包含全部文件和目錄的元信息,記錄每一個文件在各個塊數據節點的信息
  • datanode 工做節點
    • 受 client 和 namenode 調度會存儲和檢索數據塊

用戶如何訪問 HDFS?

用戶能夠經過 client 與 namenode 和 datanode 的交互來訪問整個文件系統。

使用 Java 客戶端須要使用 maven 引入對應的 jar 包

<!-- hadoop 部分 begin -->
        <dependency>
            <groupId>org.apache.hadoop</groupId>
            <artifactId>hadoop-client</artifactId>
            <version>${hadoop.version}</version>
        </dependency>

此處的 hadoop.version 與 hadoop 版本對應,如

<hadoop.version>2.6.5</hadoop.version>

如何對 namenode 容錯?

namenode 中存儲的是文件系統的總體信息及各個文件的元信息。若是它損壞了,就會致使文件系統上全部的數據就丟失了。所以對 namenode 容錯很是重要, hadoop 提供了兩種機制:

  1. 備份組成文件系統元數據持久狀態的文件

    • 配置讓 namenode 在多個文件系統上保存元數據的信息
    • 這種操做的特性是實時同步的,並且是原子操做
    • 實現方式就是在將信息寫入本地磁盤的同時,寫入一個 NFS
  2. 運行一個輔助的 namenode

    注意,這裏的 namenode 並不是是備用 (standby) namenode。

    它的做用就是按期合併編輯日誌與命名空間鏡像,從而防止編輯日誌過大。而且會保存合併後的命名空間鏡像的副本,並在 namenode 發生故障時使用。

    反作用就是輔助 namenode 保存的狀態老是滯後於主節點,在主節點所有失效後,不免會丟失部分數據。要解決這個問題,能夠將 1 中存儲在 NFS 上的 namenode 元數據複製到輔助 namenode 做爲新的主 namenode 運行。

如何更快的訪問 datanode 中訪問頻繁的塊?

對於 datanode 中訪問頻繁的 block, 就會被顯式緩存在 datanode 的內存中,以堆外塊緩存 (off-heap block cache) 的形式存在。這樣作是爲了更快的訪問 datanode ,提升讀操做性能。

用戶或應用經過在緩存池(cache pool) 中增長一個 cache directive 告知 namenode 須要緩存哪些文件以及存放多久。cache pool 是一個用來管理緩存權限和資源使用的管理性分組。

如何擴展 namenode 以存儲更多的文件?

因爲 namenode 中會在內存中保存文件系統中的樹信息和文件元信息。當文件太多時,就會致使文件系統的信息容量要大於 namenode 的內存限制。這種狀況下,就不能再存儲更多的文件了。所以須要對 namenode 進行橫向擴展。 HDFS Federation 聯邦 HDFS 就是用來解決這個問題的。

HDFS 中的高可用性設計

HDFS 在設計時的目標就是要可運行在商用廉價計算機集羣上,而對於大型集羣來講,節點故障率仍是很是高的。這也就表示 HDFS 遇到節點故障時,可以自動處理這些故障,保持集羣的繼續運行,而不會讓用戶察覺到明顯的中斷。也就是 HDFS 的高可用性設計。

在上一節,咱們瞭解到 HDFS 中最關鍵的節點就是 namenode,它保存了整個文件系統樹以及文件,目錄的元信息。若是它出現了 單點失效 SOFP (single point of failure) 的問題,那麼 HDFS 中全部的功能包括 client 都沒法執行任何讀取,寫入等操做了。所以, 一個 namenode 節點失效後,如何讓集羣保持繼續運行,並且不會讓用戶察覺到是保證 HDFS 可用性的關鍵。

如何處理 namenode 單點失效問題?

namenode 配置成活動(active)—備用(standy)兩個節點,當活動 namenode 節點失效後,備用 namenode 就會接管它的任務,並繼續處理來自 client 的請求,這些過程對用戶是透明的,而且不會有明顯的中斷。

要實現這個功能,須要在架構上作以下修改:

  • namenode 之間要實現編輯日誌的共享
  • datanode 要同時向兩個 namenode 發送塊處理報告
  • client 要使用特定的機制來處理 namenode 失效問題,而且這一機制對用戶是透明的
  • 備用 namenode 中包含輔助 namenode 的功能

namenode 間如何共享編輯日誌?

namenode 之間須要經過高可用性共享存儲來共享編輯日誌。

存儲方案有兩種:

  • NFS
  • 羣體日誌管理器 QJM(quorum journal manager)。

這裏重點說明下 QJM。QJM 就是爲了專門提供高可用性編輯日誌而設計的,被推薦在大多數 HDFS 部署中使用。QJM 是由一組 journal node 節點組成的,典型狀況下是 3 個 journal 節點。每次編輯操做時,都會將日誌寫入到大多數節點。

namenode 如何能快速故障切換?

因爲 datanode 同時向兩個 namenode 發送塊處理報告,而且 namenode 會將最新的編輯日誌和數據塊信息存儲在內存中。當活動 namenode 失效後,備用 namenode 可以在大約幾十秒的時間內就能實現任務接管。這個過程都是由故障轉移控制器(failover controller) 來實現的。

failover controller 故障轉移控制器管理着活動 namenode 轉移爲備用 namenode 的轉換過程。默認會使用 zookeeper 來確保有且僅有一個活動 namenode。

每一個 namenode 都運行着一個故障轉移控制器,其工做就是經過一個心跳機制,監視 活動 namenode 是否失效,而且在 namenode 失效時自動進行故障切換。除了自動故障轉移外,管理員也能夠手動發起故障轉移,將兩個 namenode 節點互換角色。

如何規避非平穩故障轉移?

假設一個 hadoop 集羣中運行着兩個 namenode 節點,節點 A 和 節點 B。此時A 會活動節點,B 爲備用節點,兩個節點都正常運行。

在某個時間點,因爲網速很是慢或者網絡被分割的緣由,節點 B 的故障轉移控制器沒法經過心跳機制聯繫上節點 A,但此時節點 A 也在正常運行。

在通過幾十秒的時間後,節點 B 就認爲節點 A 已經失效,要切換爲活動節點,但此時節點 A 也正在活動,這種狀況就稱爲非平穩故障轉移。

而此時咱們要作的就是確保以前的活動節點 A 再也不活動(不能同時出現兩個活動節點),這種行爲就稱爲「規避」。

對於 QJM 共享存儲來講,規避方式就是同一時間 QJM 只容許一個 namenode 像編輯日誌中寫入數據。先前活動的節點訪問 QJM 時, 會設置一個規避命令來殺死 該namenode。

小結

每一種技術實現都是和需求,背景息息相關的。只有理解了需求和背景,針對技術方案的改進看起來才能是那麼的天然和必然。

文末附上根據 《hadoop 權威指南》整理的 HDFS 概念思惟導圖,從總體上梳理下HDFS 知識點脈絡。

HDFS concept

參考文檔

  1. Hadoop: The Definitive Guide
  2. HDFS Architecture
相關文章
相關標籤/搜索