淺析HDFS架構和設計

做者 | 大尊html

hdfs是hadoop的分佈式文件系統,即Hadoop Distributed Filesystem。下面主要講下HDFS設計中的比較重要的點,使讀者能經過簡短的文章一窺HDFS的全貌,適合對HDFS有一點了解,可是對HDFS又感到困惑的初學者。本文主要參考的是hadoop 3.0的官方文檔。java

連接:hadoop.apache.org/docs/curren…node

當數據集的大小超過了一臺物理機所能存儲的能力時,就須要將它進行分區並存儲到若干不一樣的獨立的計算機上,其中管理跨多臺計算機存儲的文件系統稱爲分佈式文件系統。shell

目錄

  • 使用HDFS的場景apache

  • HDFS的工做模式瀏覽器

  • 文件系統命名空間(namespace)安全

  • 數據複製bash

  • 文件系統元數據的持久化服務器

  • 通信協議網絡

  • 健壯性

  • 數據組織

  • 可訪問性

  • 存儲空間回收

一、使用HDFS的場景

HDFS適合於以流式數據訪問模式來存儲超大的文件。即一次寫入,屢次讀取,在數據集上長時間進行各類分析,每次分析都涉及該數據集數據的大部分甚至所有,對於超大文件,hadoop目前以支持存儲PB級數據。

HDFS並不適合要求低時間延遲數據訪問的應用,由於HDFS是爲高數據吞吐量應用而優化的,這就有可能以時間延遲大爲代價。

HDFS文件系統所能存儲的文件總數受限於namenode的內存容量,根據經驗,100百萬的文件,且每一個文件佔一個數據塊,那至少須要300MB的內存。

目前hadoop文件可能只有一個writer,並且寫操做老是將數據添加在文件末尾,不支持在文件的任意位置進行修改。

相對於普通文件系統的數據塊,HDFS也有塊的概念,默認是128MB,HDFS上的文件也被劃分紅塊大小的多個分塊,做爲獨立的存儲單元,不過HDFS中小於一個塊大小的文件不會佔據整個塊的空間。若是沒有特別指出,文中提到的塊特指HDFS的塊。

爲什麼HDFS的塊如此之大,其目的是爲了最小化尋址開銷。這個數也不能設置的過大,mapreduce中的map任務一般一次只處理一個塊中的數據,所以若是任務數太少,做業的運行速度就會比較慢。

二、HDFS的工做模式

HDFS採用master/slave架構,即一個namenode(管理者)多個datanode(工做者)。

namenode負責管理文件系統的命名空間。維護着文件系統樹和整個樹內全部的文件和目錄,這些信息都保存在兩個文件中,命名空間鏡像文件和編輯日誌文件。namenode也記錄了每一個文件中各個塊所在的數據節點信息。datanode是文件系統的工做節點,它們須要存儲並檢索數據塊(受客戶端或namenode調度),並按期向namenode發送它們所存儲的塊的列表。

若是沒有namenode,文件系統將沒法使用,由於咱們不知道如何根據datanode的塊重建文件,因此對namenode進行容錯是很是重要的。爲此hadoop提供了兩種機制。

第一種機制是備份那些組成文件系統元數據持久狀態的文件。通常,在將持久化文件寫入本地磁盤的同時,寫入遠程掛載的NFS。

第二種方法是運行一個輔助namenode,這個輔助namenode按期經過編輯日誌合併命名空間鏡像,並在本地保存合併後的命名空間鏡像的副本,在namenode發生故障時啓用。可是在主節點失效時,不免會丟失部分數據,這時能夠把存儲在NFS的namenode元數據複製到輔助的namenode上做爲新的namenode運行。這其中涉及到故障轉移的機制。稍後會作一點分析。

三、文件系統命名空間(namespace)

HDFS支持傳統的層次型文件組織結構。用戶或者應用程序能夠建立目錄,而後將文件保存在這些目錄裏。

文件系統名字空間的層次結構和大多數現有的文件系統相似:用戶能夠建立、刪除、移動或重命名文件。HDFS支持用戶磁盤配額和訪問權限控制,目前還不支持硬連接和軟連接。可是HDFS架構並不妨礙實現這些特性。

Namenode負責維護文件系統的名字空間,任何對文件系統名字空間或屬性的修改都將被Namenode記錄下來。應用程序能夠設置HDFS保存的文件的副本數目。文件副本的數目稱爲文件的副本系數,這個信息也是由Namenode保存的。

四、數據複製

HDFS被設計成可以在一個大集羣中跨機器可靠地存儲超大文件。它將每一個文件存儲成一系列的數據塊,除了最後一個,全部的數據塊都是一樣大小的。

爲了容錯,文件的全部數據塊都會有副本。每一個文件的數據塊大小和副本系數都是可配置的。 應用程序能夠指定某個文件的副本數目。副本系數能夠在文件建立的時候指定,也能夠在以後改變。

HDFS中的文件都是一次性寫入的,而且嚴格要求在任什麼時候候只能有一個寫入者。

Namenode全權管理數據塊的複製,它週期性地從集羣中的每一個Datanode接收心跳信號和塊狀態報告(Blockreport)。當一個Datanode啓動時,它會掃描本地文件系統,產生一個這些本地文件對應的全部HDFS數據塊的列表,而後做爲報告發送到Namenode,這個報告就是塊狀態報告。接收到心跳信號意味着該Datanode節點工做正常。塊狀態報告包含了一個該Datanode上全部數據塊的列表。

數據塊列表獲取。查看數據塊的健康狀態:hdfs fsck / -files -block或者hdfs fsck /

HDFS的數據塊存儲在以_blk爲前綴名的文件中,每一個塊還有一個相關的帶有.meta後綴的元數據文件,元數據文件包括頭部和該塊各區段的一系列校驗和。

當數據塊的數量增長到必定規模時,datanode會建立一個子目錄來存放新的數據塊及元數據信息。若是當前目錄已經存儲了64個(經過dfs.datanode.numlocks屬性設置)數據塊時,就建立一個子目錄,終極目標是設計一顆高扇出的目錄樹。

若是dfs.datanode.data.dir屬性指定了不一樣磁盤的多個目錄,那麼數據塊會以輪轉(round-robin)的方式寫入到各個目錄中。

在每一個datanode上也會運行一個塊掃描器,按期檢測本節點上的全部塊,從而在客戶端讀取到壞塊以前就及時的檢測和修復壞塊。默認狀況下每隔3週會測試塊的狀態,並對可能的故障進行修復。

用戶能夠經過http://datanode:50070/blockScannerReport獲取該datanode的塊檢測報告。

副本存放

副本的存放是HDFS可靠性和性能的關鍵。優化的副本存放策略是HDFS區分於其餘大部分分佈式文件系統的重要特性。這種特性須要作大量的調優,並須要經驗的積累。HDFS採用一種稱爲機架感知(rack-aware)的策略來改進數據的可靠性、可用性和網絡帶寬的利用率。目前實現的副本存放策略只是在這個方向上的第一步。

經過一個機架感知的過程,Namenode能夠肯定每一個Datanode所屬的機架id。一個簡單但沒有優化的策略就是將副本存放在不一樣的機架上。這樣能夠有效防止當整個機架失效時數據的丟失,而且容許讀數據的時候充分利用多個機架的帶寬。這種策略設置能夠將副本均勻分佈在集羣中,有利於當組件失效狀況下的負載均衡。可是,由於這種策略的一個寫操做須要傳輸數據塊到多個機架,這增長了寫的代價。

在大多數狀況下,副本系數是3,HDFS的存放策略是將一個副本存放在本地機架的節點上,一個副本放在同一機架的另外一個節點上,最後一個副本放在不一樣機架的節點上。這種策略減小了機架間的數據傳輸,這就提升了寫操做的效率。

而在現實中,在hadoop2.0中,datanode數據副本存放磁盤選擇策略有兩種方式:

第一種是沿用hadoop1.0的磁盤目錄輪詢方式,實現類:

RoundRobinVolumeChoosingPolicy.java

第二種是選擇可用空間足夠多的磁盤方式存儲,實現類:AvailableSpaceVolumeChoosingPolicy.java

第二種策略對應的配置項是:

若是不配置,默認使用第一種方式,既輪詢選擇磁盤來存儲數據副本,可是輪詢的方式雖然可以保證全部磁盤都可以被使用,可是常常會出現各個磁盤直接數據存儲不均衡問題,有的磁盤存儲得很滿了,而有的磁盤可能還有不少存儲空間沒有獲得利用,全部在hadoop2.0集羣中,最好將磁盤選擇策略配置成第二種,根據磁盤空間剩餘量來選擇磁盤存儲數據副本,這樣同樣能保證全部磁盤都能獲得利用,還能保證全部磁盤都被利用均衡。

在採用第二種方式時還有另外兩個參數會用到:

默認值是10737418240,既10G,通常使用默認值就行。官方解釋爲,首先計算出兩個值,一個是全部磁盤中最大可用空間,另一個值是全部磁盤中最小可用空間,若是這兩個值相差小於該配置項指定的閥值時,則就用輪詢方式的磁盤選擇策略選擇磁盤存儲數據副本。

默認值是0.75f,通常使用默認值就行。官方解釋爲,有多少比例的數據副本應該存儲到剩餘空間足夠多的磁盤上。該配置項取值範圍是0.0-1.0,通常取0.5-1.0,若是配置過小,會致使剩餘空間足夠的磁盤實際上沒分配足夠的數據副本,而剩餘空間不足的磁盤取須要存儲更多的數據副本,致使磁盤數據存儲不均衡。

副本選擇

爲了下降總體的帶寬消耗和讀取延時,HDFS會盡可能讓讀取程序讀取離它最近的副本。若是在讀取程序的同一個機架上有一個副本,那麼就讀取該副本。若是一個HDFS集羣跨越多個數據中心,那麼客戶端也將首先讀本地數據中心的副本。

安全模式

Namenode啓動後會進入一個稱爲安全模式的特殊狀態。 處於安全模式的Namenode是不會進行數據塊的複製的。Namenode從全部的 Datanode接收心跳信號和塊狀態報告。塊狀態報告包括了某個Datanode全部的數據塊列表。每一個數據塊都有一個指定的最小副本數。

當Namenode檢測確認某個數據塊的副本數目達到這個最小值(最小值默認是1,由dfs.namenode.replication.min屬性設置),那麼該數據塊就會被認爲是副本安全(safely replicated)的;在必定百分比(這個參數可配置,默認是0.999f,屬性值爲dfs.safemode.threshold.pct)的數據塊被Namenode檢測確認是安全以後(加上一個額外的30秒等待時間),Namenode將退出安全模式狀態。接下來它會肯定還有哪些數據塊的副本沒有達到指定數目,並將這些數據塊複製到其餘Datanode上。

若是datanode丟失的block達到必定的比例,namenode就會一直處於安全模式即只讀模式。

當namenode處於安全模式時,該怎麼處理?

找到問題所在,進行修復(好比修復宕機的datanode)。

或者能夠手動強行退出安全模式(沒有真正解決問題): hdfs namenode --safemode leave。

在hdfs集羣正常冷啓動時,namenode也會在safemode狀態下維持至關長的一段時間,此時你不須要去理會,等待它自動退出安全模式便可。

用戶能夠經過dfsadmin -safemode value 來操做安全模式,參數value的說明以下:

enter - 進入安全模式

leave - 強制NameNode離開安全模式

get - 返回安全模式是否開啓的信息

wait - 等待,在執行某條命令前先退出安全模式。

五、文件系統元數據的持久化

Namenode上保存着HDFS的名字空間。對於任何對文件系統元數據產生修改的操做,Namenode都會使用一種稱爲EditLog的事務日誌記錄下來。例如,在HDFS中建立一個文件,Namenode就會在Editlog中插入一條記錄來表示;一樣地,修改文件的副本系數也將往Editlog插入一條記錄。Namenode在本地操做系統的文件系統中存儲這個Editlog。

整個文件系統的名字空間,包括數據塊到文件的映射、文件的屬性等,都存儲在一個稱爲FsImage的文件中,這個文件也是放在Namenode所在的本地文件系統上。

Namenode在內存中保存着整個文件系統的名字空間和文件數據塊映射(Blockmap)的映像(即FsImage)。這個關鍵的元數據結構設計得很緊湊,於是一個有4G內存的Namenode足夠支撐大量的文件和目錄。

當Namenode啓動時,或者檢查點達到配置文件中的閥值,它從硬盤中讀取Editlog和FsImage,將全部Editlog中的事務做用在內存中的FsImage上,並將這個新版本的FsImage從內存中保存到本地磁盤上,而後刪除舊的Editlog,由於這個舊的Editlog的事務都已經做用在FsImage上了。這個過程稱爲一個檢查點(checkpoint)。

hdfs dfsadmin -fetchImage fsimage.backup

//手動從namenode獲取最新fsimage文件,並保存爲本地文件。

由於編輯日誌會無限增加,那麼恢復編輯日誌的過程就會比較長,解決方案是,運行輔助namenode,爲主namenode內存中的文件系統元數據建立檢查點。最終主namenode擁有最新的fsimage文件和更小的edits文件。

這也解釋了輔助namenode和主namenode擁有相近內存需求的緣由(輔助namenode也須要把fsimage文件載入內存)。

建立檢查點的觸發條件受兩個配置參數控制,

dfs.namenode.checkpoint.period屬性(輔助namenode每隔一段時間就建立檢查點,單位s)。dfs.namenode.checkpoint.txns,若是從上一個檢查點開始編輯日誌大小達到多少的事務數時,建立檢查點。

在主namenode發生故障時(假設沒有備份),就能夠從輔助的namenode上恢復數據。有兩種實現方式。

方法一,將相關的存儲目錄複製到新的namenode中 。

方法二,使用-importCheckpoint選項啓動namenode守護進程,從而將輔助namenode用做新的主namenode,有個前提時,dfs.namenode.dir屬性定義的目錄中沒有元數據時。

六、通信協議

全部的HDFS通信協議都是創建在TCP/IP協議之上。客戶端經過一個可配置的TCP端口鏈接到Namenode,經過ClientProtocol協議與Namenode交互。而Datanode使用DatanodeProtocol協議與Namenode交互。

一個遠程過程調用(RPC)模型被抽象出來封裝ClientProtocol和Datanodeprotocol協議。在設計上,Namenode不會主動發起RPC,而是響應來自客戶端或 Datanode 的RPC請求。

七、健壯性

HDFS的主要目標就是即便在出錯的狀況下也要保證數據存儲的可靠性。

常見的三種出錯狀況是:Namenode出錯, Datanode出錯和網絡割裂(network partitions)。

心跳檢測,磁盤數據錯誤和從新複製。

每一個Datanode節點週期性地向Namenode發送心跳信號。網絡割裂可能致使一部分Datanode跟Namenode失去聯繫。Namenode經過心跳信號的缺失來檢測這一狀況,並將這些近期再也不發送心跳信號Datanode標記爲宕機,不會再將新的IO請求發給它們。任何存儲在宕機Datanode上的數據將再也不有效。

Datanode的宕機可能會引發一些數據塊的副本系數低於指定值,Namenode不斷地檢測這些須要複製的數據塊,一旦發現就啓動複製操做。

設置合適的datanode心跳超時時間,避免用datanode不穩定致使的複製風暴。

在下列狀況下,也可能須要從新複製:某個Datanode節點失效,某個副本遭到損壞,Datanode上的硬盤錯誤,或者文件的副本系數增大。

集羣均衡(針對datanode)

HDFS的架構支持數據均衡策略。若是某個Datanode節點上的空閒空間低於特定的臨界點,按照均衡策略系統就會自動地將數據從這個Datanode移動到其餘空閒的Datanode。

個文件的請求忽然增長,那麼也可能啓動一個計劃建立該文件新的副本,而且同時從新平衡集羣中的其餘數據。這個均衡策略目前尚未實現。

數據完整性(針對datanode)

從某個Datanode獲取的數據塊有多是損壞的,損壞多是由Datanode的存儲設備錯誤、網絡錯誤或者軟件bug形成的。HDFS客戶端軟件實現了對HDFS文件內容的校驗和(checksum)檢查。

當客戶端建立一個新的HDFS文件,會計算這個文件每一個數據塊的校驗和,並將校驗和做爲一個單獨的隱藏文件保存在同一個HDFS名字空間下。當客戶端獲取文件內容後,它會檢驗從Datanode獲取的數據跟相應的校驗和文件中的校驗和是否匹配,若是不匹配,客戶端能夠選擇從其餘Datanode獲取該數據塊的副本。

元數據磁盤錯誤(針對namenode出錯)

FsImage和Editlog是HDFS的核心數據結構。若是這些文件損壞了,整個HDFS實例都將失效。於是,Namenode能夠配置成支持維護多個FsImage和Editlog的副本。任何對FsImage或者Editlog的修改,都將同步到它們的副本上。這種多副本的同步操做可能會下降Namenode每秒處理的名字空間事務數量。然而這個代價是能夠接受的,由於即便HDFS的應用是數據密集的,它們也非元數據密集的。當Namenode重啓的時候,它會選取最近的完整的FsImage和Editlog來使用。

另一個可選方案是經過共享存儲NFS或一個分佈式編輯日誌(也叫journal)實現多namenode節點(HA),來加強故障恢復能力。

在HDFS HA的實現中,配置了一對active-standby的namenode,當活動的namenode失效,備用的namenode就會接管它的任務並開始服務於客戶端的請求。

實現HA須要在架構上作以下修改:

namenode之間經過高可用共享存儲實現編輯日誌的共享,當備用namenode接管工做以後,它將通讀共享編輯日誌直到末尾,實現與active namenode狀態同步,並繼續讀取由活動namenode寫入的新條目。

datanode須要同時向兩個namenode發送數據塊處理報告,由於數據塊映射信息存在namenode的內存,而非硬盤。

客戶端使用特定的機制處理namenode的失效,這一機制對於用戶是透明的。

輔助namenode的角色被namenode所包含,備用namenode爲活動的namenode命名空間設置週期性檢查。

快照

快照支持某一特定時刻的數據的複製備份。利用快照,可讓HDFS在數據損壞時恢復到過去一個已知正確的時間點。

八、數據組織

數據塊

HDFS被設計成支持大文件,適用HDFS的是那些須要處理大規模的數據集的應用。這些應用都是隻寫入數據一次,但卻讀取一次或屢次,而且讀取速度應能知足流式讀取的須要。HDFS支持文件的「一次寫入屢次讀取」語義。一個典型的數據塊大小是128MB。於是,HDFS中的文件老是按照128M被切分紅不一樣的塊,每一個塊儘量地存儲於不一樣的Datanode中。

流水線複製

當客戶端向HDFS文件寫入數據的時候,一開始是寫到本地臨時文件中。假設該文件的副本系數設置爲3,當本地臨時文件累積到一個數據塊的大小時,客戶端會從Namenode獲取一個Datanode列表用於存放副本。而後客戶端開始向第一個Datanode傳輸數據,第一個Datanode一小部分一小部分(4 KB)地接收數據,將每一部分寫入本地倉庫,並同時傳輸該部分到列表中第二個Datanode節點。第二個Datanode也是這樣,一小部分一小部分地接收數據,寫入本地倉庫,並同時傳給第三個Datanode。最後,第三個Datanode接收數據並存儲在本地。

所以,Datanode能流水線式地從前一個節點接收數據,並在同時轉發給下一個節點,數據以流水線的方式從前一個Datanode複製到下一個。

九、可訪問性

HDFS給應用提供了多種訪問方式。用戶能夠經過Java API接口訪問,也能夠經過C語言的封裝API訪問,還能夠經過瀏覽器的方式訪問HDFS中的文件。經過WebDAV協議訪問的方式正在開發中。

DFSShell

HDFS以文件和目錄的形式組織用戶數據。它提供了一個命令行的接口(DFSShell)讓用戶與HDFS中的數據進行交互。命令的語法和用戶熟悉的其餘shell(例如 bash, csh)工具相似。下面是一些動做/命令的示例:

DFSAdmin

DFSAdmin 命令用來管理HDFS集羣。這些命令只有HDSF的管理員才能使用。下面是一些動做/命令的示例:

瀏覽器接口

一個典型的HDFS安裝會在一個可配置的TCP端口開啓一個Web服務器用於暴露HDFS的名字空間。用戶能夠用瀏覽器來瀏覽HDFS的名字空間和查看文件的內容。

http://ip:50070

十、存儲空間回收

文件的刪除和恢復

當垃圾回收生效時,經過fs shell刪除的文件並無馬上從HDFS中刪除。實際上,HDFS會將這個文件重命名轉移到user//.Trash目錄。只要文件還在.Trash目錄中,該文件就能夠被迅速地恢復。文件在Trash中保存的時間是可配置的,當超過這個時間時,Namenode就會將該文件從名字空間中刪除。刪除文件會使得該文件相關的數據塊被釋放。注意,從用戶刪除文件到HDFS空閒空間的增長之間會有必定時間的延遲。

只要被刪除的文件還在.Trash目錄中,用戶就能夠恢復這個文件。若是用戶想恢復被刪除的文件,他/她能夠瀏覽.Trash目錄找回該文件。

減小副本系數

當一個文件的副本系數被減少後,Namenode會選擇過剩的副本刪除。下次心跳檢測時會將該信息傳遞給Datanode。Datanode遂即移除相應的數據塊,集羣中的空閒空間加大。一樣,在調用setReplication API結束和集羣中空閒空間增長間會有必定的延遲。

【本文爲數瀾用戶原創內容,轉載時必須標註文章的來源,文章連接,文章做者等基本信息】

相關文章
相關標籤/搜索