Apache Hadoop文件翻譯之一(HDFS架構)

Kooola大資料發表於2018-09-29

Apache Hadoop文件翻譯之一(HDFS架構)

Apache Hadoop專案為高可用、可擴充套件、分散式計算開發開源軟體。Apache Hadoop軟體庫是一個平臺,它使用簡單的程式設計模型讓跨機器上大資料量的分散式計算變得簡單。 它旨在從單個伺服器擴充套件到數千臺計算機,每臺計算機都提供本地計算和儲存。庫本身被設計用來在軟體層面檢測和處理故障,而不是依賴硬體來提供高可用性,因此,在計算機叢集之上提供高可用性服務,每個計算機都可能容易出現故障。

介紹

HDFS是一個被設計用來執行在商用機器上的分散式檔案系統。它跟現有的分散式檔案系統有很多相似之處,但是,區別也很大。HDFS容錯率高,並且被設計為部署在廉價機器上。HDFS提供對應用程式資料的高吞吐量訪問,適用於具有大型資料集的應用程式。HDFS放寬了一些POSIX要求,以實現對檔案系統資料的流式訪問。HDFS最開始被構建是用來作為Nutch搜尋引擎專案的基礎設施。HDFS是Apache hadoop核心專案的一部分。專案地址:hadoop.apache.org/

假設和目標

硬體故障

硬體故障很常見。一個HDFS示例應該是包含成百上千臺伺服器,每臺伺服器儲存檔案系統的部分資料。事實上,存在大量元件並且每個元件都有可能出現故障,這意外著有些元件可能一直無法正常工作。因此,檢測故障並且自動從故障中快速恢復是HDFS架構的核心目標。

流資料訪問

在HDFS上執行的程式需要對其資料集進行流式訪問。它們不是執行在普通檔案系統上的普通應用程式。HDFS被設計更多是作為批處理來使用,而不是使用者的互動式使用。重點是資料訪問的高吞吐量而不是資料訪問的低延遲。POSIX強加了許多針對HDFS的應用程式不需要的硬性要求。

大資料集

執行在HDFS上的程式使用者大量的資料集。HDFS中,一個普通檔案可以達到千兆到太位元組。因此,HDFS調整為支援大檔案。它應該提供高聚合資料頻寬並擴充套件到單個叢集中的數百個節點。 它應該在單個例項中支援數千萬個檔案。

簡單的一致性模型

HDFS程式需要一個一次寫入多次讀取的檔案訪問模型。一次建立、寫入和關閉的檔案,除了追加和截斷之外,不需要更改。可以在檔案尾部追加內容,但是不能在任意位置進行修改。這種假設簡化了一致性問題,並且提高了資料訪問的吞吐量。這種模型非常適合Mapreduce程式以及網路爬蟲。

移動計算比移動資料代價更小

當計算所需要的資料距離計算越近時,計算的效率越高,當資料量越大時,這個效率提升更明顯。越少的網路阻塞越能提高系統整體的吞吐量。這樣,我們可以認為,將計算遷移到資料附近比將資料遷移到計算附近更高效。HHDFS為應用程式提供了介面,使其自身更靠近資料所在的位置。

跨異構硬體和軟體平臺的可移植性

HDFS被設計成易於從一個平臺移植到另一個平臺。這有助於HDFS的普及。

Namenode和DataNodes

HDFS有一個主從架構。一個HDFS叢集包含一個Namenode,Namenode管理檔案系統的名稱空間以及調整客戶端對檔案的訪問。此外,還有一定數量的Datanode,叢集中通常一個節點一個Datanode,用來管理其執行節點上的儲存。HDFS公開檔案系統名稱空間,並允許使用者資料儲存在檔案中。叢集內部,一個檔案被分成一個或多個blocks並且這些blocks儲存在一些Datanode上。Namenode執行檔案系統名稱空間操作,例如開啟、關閉、重新命名檔案和資料夾。Namenode還決定blocks到Datanode的對映。Datanode負責服務於系統客戶端的讀和寫。DataNode還根據NameNode的指令執行塊建立,刪除和複製。

Apache Hadoop文件翻譯之一(HDFS架構)

Namenode和Datanode時設計用於執行在商用機器上的軟體。這些機器通常執行linux作業系統。HDFS是JAVA語言編寫的,所以任何支援JAVA的機器都能執行Namenode和Datanode軟體。使用高度可移植的Java語言意味著HDFS可以部署在各種各樣的機器上。普遍的部署方式是在一臺專用機器上單獨執行Namenode軟體。叢集中其他機器執行Datanode軟體。架構支援在一臺機器上執行多個Datanode,但是實際部署很少這樣做。 一個叢集中只存在一個Namenode極大簡化了系統的架構。Namenode管理整個HDFS的後設資料。系統被設計為任何使用者資料都不流經Namenode。

檔案系統名稱空間

HDFS支援傳統的檔案分層組織。使用者或程式可以建立目錄以及儲存檔案到目錄中。HDFS檔案系統名稱空間層次結構跟其他現有檔案系統類似:比如建立檔案和刪除檔案,將檔案從一個目錄移到另一個目錄,或者重新命名檔案。HDFS支援使用者配額訪問許可權。HDFS不支援硬連線或軟連線,但是不排除在未來的版本中實現。 Namenode維護檔案系統的名稱空間。檔案系統名稱空間或其屬性的更改都由Namenode來記錄。應用程式可以指定檔案的副本數量,該文字由HDFS來維護。檔案的副本數稱為該檔案的複製因子,該資訊由NameNode儲存。

資料複製

HDFS被設計用來可靠地在叢集中大量機器上儲存大檔案。它以一系列塊的形式儲存每一個檔案。檔案塊被複制多份以提高容錯性。每個檔案的塊大小和複製因子是可配置的。 一個檔案除了最後一個塊以外,其他塊都是相同大小。當設定塊長度可變時,使用者可以開啟一個新的塊而不需要在最後的塊上進行追加以達到配置的固定大小。 應用程式可以指定檔案的副本數量。複製因子在檔案建立時指定並能在隨後進行修改。HDFS中檔案是一次性寫入(除非追加和截斷)並且任何時候只有一個寫入者。 有關塊的複製,NameNode全權負責。Namenode定期接收叢集中Datanode的心跳和塊資訊報告。接收到心跳錶明Datanode正常工作。塊資訊報告(Blockreport)包含DataNode上所有塊的列表。

Apache Hadoop文件翻譯之一(HDFS架構)

副本選址

副本的選址對HDFS的可靠性和效能起到至關重要的作用。優化副本的選址使HDFS區別於其他分散式檔案系統。這是一個需要大量除錯和經驗的特性。機架感知式的選址策略的目標是為了提供資料可靠性、可用性以及頻寬利用率。目前的副本選址策略的實現是在這個方向上的第一次努力。實現這個策略的短期目標是在生產系統中進行驗證,掌握更多行為並建立一個基礎來測試和研究更加複雜的策略。

HDFS執行在一系列的叢集主機上,這些主機通常分佈在各個機架上。跨機架上的兩個不同主機間資訊交換需要經過交換機。在大多數情況下,同一機架中的計算機之間的網路頻寬大於不同機架中的計算機之間的網路頻寬。

Namenode通過Hadoop Rack Awareness 過程來決定每個Datanode隸屬於哪個機架id。一個簡單但是非最佳的策略是將副本放在不同機架上。這樣,當一整個機架出現故障時能夠防止資料丟失,並且讀取資料能使用到不同機架上的頻寬。但是,這種策略增加了寫操作代價,因為需要傳輸塊到不同機架上。

當副本數為3時,HDFS放置策略通常是將一個副本放在本機架的一個節點上,將另一個副本放在本機架的另一個節點,最後一個副本放在不同機架的不同節點上。該策略可以減少機架之間寫入流量,從而提高寫入效能。機架出現故障的概率要比機器出現故障的概率低,這個策略不會影響資料可靠性和可用性的保證。但這種策略會降低資料讀取時的網路頻寬,因為資料只放置在兩個機架上而不是三個。這種策略下,檔案的副本不是均勻的分佈在各個機架上。三分一個的副本放置在一個節點上,三分之二的副本放置在一個機架上,而另外三分之一均勻分佈在剩餘的機架上。這個策略提高了寫效能而不影響資料可靠性和讀效能。

當前,這裡介紹的預設副本放置策略是一項正在進行的工作。

副本選擇

為了降低頻寬消耗以及讀取延時,HDFS嘗試讓需要讀取的副本跟讀取者更近。如果存在一個副本在客戶端節點所在的同個機架上,那麼這個副本是滿足讀取需求的首選。如果HDFS叢集橫跨多個資料中心,那麼在本地資料中心的副本將是優先於其他遠端副本。

安全模式

Namenode剛啟動時會進入一個特殊階段,我們稱這個階段為安全模式。當Namenode處於安全模式時,不會發生資料塊的複製。Namenode接收來自Datanode的心跳以及塊報告資訊。塊報告包含Datanode持有的一些列資料塊。每個塊都指定最小副本數。當一個資料塊被NameNode檢查確保它滿足最小副本時數,它被認為是安全的。資料被Namenode檢入,當檢入達到一個百分比(該百分比可配置)時,Namenode退出安全模式。然後Namenode會確認那些副本數小於指定數量的資料塊列表,並且複製這些塊到其他Datanode上。

檔案系統後設資料的永續性

HDFS名稱空間儲存在Namenode上。NmaeNode使用一個稱之為EditLog的事務日誌持續地記錄發生在檔案系統後設資料的每一個改變。例如,在HDFS中建立一個檔案,Namenode將插入一條記錄到EditLog中。同樣,修改檔案的複製因子也會導致一條新的記錄插入EditLog中。Namenode使用本地作業系統檔案來儲存EditLog。整個檔案系統名稱空間(包括塊到檔案的對映以及檔案系統屬性)儲存在一個稱為FsImage的檔案中。FsImage同樣儲存在Namenode的本地檔案系統中。

Namenode將整個檔案系統的名稱空間以及塊對映資訊儲存在記憶體中。當Namenode啟動時,或者可配置閾值的檢查點被觸發時,Namenode便從磁碟中讀取FsImage和EditLog,將EditLog中的事務應用到表示FsImage的記憶體中,然後將最新的FsImage記憶體重新整理到磁碟上。然後可以截斷舊的EditLog,因為新版的EditLog已經持久化到FsImage中。以上整個過程稱為檢查點(checkpoint)。檢查點的目的是通過獲取檔案系統後設資料的快照並將其儲存到FsImage來確保HDFS具有檔案系統後設資料的一致檢視。即使讀取FsImage很高效,直接向FsImage增加編輯並不高效。因此針對每次編輯,我們會放在EditLog中而不是直接修改FsImage。檢查點期間,EditLog的變更資訊會應用到FsImage上。可以以秒為單位的給定時間間隔(dfs.namenode.checkpoint.period)觸發檢查點,或者在累積給定數量的檔案系統事務(dfs.namenode.checkpoint.txns)之後觸發檢查點。當兩者均被設定,則哪個先生效就直接觸發檢查點。

Datanode將HDFS資料儲存在本地檔案系統的檔案中。Datanode對HDFS檔案沒有意識,它只是儲存HDFS資料的每個塊,並儲存在本地檔案系統中的各個檔案中。Datanode不會在相同目錄下建立所有檔案,而是每個目錄中有一個最佳檔案數,並適當建立子目錄。將所有檔案放在同一個目錄下不太明智,因為本地檔案系統或許不能有效支援在一個目錄下面存放海量檔案。當一個Datanode啟動時,它將掃描本地檔案系統,生成所有HDFS資料塊的列表(這些資料塊對應每一個本地檔案),併傳送報告給Namenode。這個報告我們稱之為塊報告。

通訊協議

所有HDFS協議均位於TCP/IP之上。一個客戶端建立一個連線到Namenode機器上的TCP埠(埠可配置)上。它使用客戶端協議與NameNode通訊。Datanode使用Datanode協議與Namenode進行通訊。一個遠端過程呼叫(RPC)封裝了客戶端協議以及Datanode協議。按照設計,NameNode永遠不會啟動任何RPC。 相反,它只響應DataNodes或客戶端發出的RPC請求。

魯棒性

HDFS的主要目標是即使在出現故障時也能可靠地儲存資料。三種常見的故障有:Namanode故障、Datanode故障以及網路分裂?

資料磁碟故障,心跳以及重新複製

每個Datanode會定期地傳送心跳資訊給你Namenode。網路分裂會導致部分Datanode失去與Namenode的聯絡。Namenode通過收不到Datanode的心跳資訊來收集這個失聯資訊。Namenode標記近期沒有心跳資訊的Datanode,並終止對這些Datanode的IO請求。在已經死亡的DataNode註冊的任何資料在HDFS將不能再有效。Datanode故障會導致一些塊的複製因子低於它們的指定值。NameNode時常地跟蹤資料塊是否需要被複制並在必要的時候啟動複製。多個原因會導致重新複製的操作,例如:Datanode不可用,副本損壞,Datanode磁碟損壞,或者檔案的複製因子增大。

將DatNode標記為死亡的超時時間適當地加長(預設超過10分鐘)是為了避免DataNode狀態改變引起的複製風暴。針對效能敏感的情況,使用者可以通過配置來設定更短的時間間隔來標記DataNode為失效,儘量避免失效的節點還繼續參與讀寫操作。

叢集重新平衡

HDFS架構相容資料再平衡方案。當一個Datanode上的剩餘空間降到一定閾值時,方案應該自動將該Datanode上的資料遷移到其他Datanode上。對於一些特定檔案的突發需求,方案應動態地建立額外的副本並重新平衡叢集中的其他資料。這種方案暫時還未實現。

資料完整性

從DataNode獲取的資料塊可能已損壞。發生損壞的原因可能是儲存裝置的故障、網路故障或者缺陷軟體。HDFS客戶端軟體對HDFS檔案的內容進行校驗和檢查。當客戶端建立一個HDFS檔案,它會計算檔案的每一個資料塊的校驗和,並將這些校驗和儲存在HDFS名稱空間中一個單獨的隱藏的檔案當中。當客戶端從DataNode獲得資料時會對對其進行校驗和,並且將之與儲存在相關校驗和檔案中的校驗和進行匹配。如果沒有,客戶端會選擇從另一個擁有該資料塊副本的DataNode上恢復資料。

後設資料磁碟故障

FsImage和EditLog是HDFS的核心資料架構。這些檔案的故障會導致HDFS例項無法工作。因為這個原因,HDFS可以被配置成支援多份FsImage和EditLog備份。任何對FsImage和EditLog的更新,都會導致其他所有FsImage和EditLog的同步更新。同步更新多份FsImge和EditLog降低NameNode能支援的每秒更新名稱空間事務的頻率。然而,頻率的降低是可以被接受,儘管HDFS應用本質上是對資料敏感,但不是對後設資料敏感。當一個NameNode重新啟動,他會選擇最新的FsImage和EditLog來使用。另一個增加容錯性已達到高可用性的選項是使用多個Namenodes,這個選項的具體實現可以為:檔案系統的共享儲存分散式的編輯日誌(稱為Journal)。後面會介紹使用方法。

快照

快照支援在特定的時間(瞬間)儲存資料的副本。我們使用的快照特徵可能是將損壞的HDFS例項回退到先前一個正常版本。

Data Organization

資料塊

HDFS被設計成支援非常大的檔案。與HDFS相容的應用程式是處理大型資料集的應用程式。這些程式一次寫入資料多次讀取,並且這些讀操作滿足流式的速度。HDFS支援一次寫入多次讀取的檔案語義。HDFS中,一個典型的塊大小是128兆。因此,一個HDFS檔案會被切割成128M大小的塊,如果可以的話,每一個大塊都會分屬於一個不同的DatNode。

複製流水線

當客戶端按照3個副本數來寫資料到HDFS檔案中,Namenode使用副本目標選擇演算法來獲取Datanode列表。這個列表包含塊副本將落地的Datanode。然後客戶端將資料寫入第一個Datanode。第一個Datanode開始分部分接收資料,將每個部分寫入其本地儲存,並將該部分傳輸到列表中的第二個Datanode。第二個Datanode開始接收資料塊的每個部分並寫入本地儲存然後傳輸到第三個Datanode。最後,第三個Datanode將資料寫入本地儲存。因此,一個Dataode能夠從上一個節點接收資料據並在同一時間將資料轉發給下一個節點。因此,資料在管道中從一個DataNode傳輸到下一個(複製流水線)。

可訪問性

應用程式可以通過多種方式來訪問HDFS。HDFS本身提供FileSystem Java API讓應用程式來訪問,這個Java Api的C語言封裝版本以及REST API同樣可以供使用者使用。另外,一個HTTP瀏覽器也可以訪問HDFS例項中的檔案。使用MFS gateway,HDFS能被安裝作為本地檔案系統的一部分。

FS Shell

HDFS提供一個稱為FS Shell的命令列介面,方便使用者與HDFS中的資料進行互動。這寫命令集合的語法跟其他我們熟悉的命令十分相似(例如bash,csh)。下面是一些動作/命令對的示例:

動作 命令
建立目錄 bin/hadoop dfs -mkdir /foodir
刪除目錄 bin/hadoop fs -rm -R /foodir
檢視檔案內容 bin/hadoop dfs -cat /foodir/myfile.txt

DFSAdmin

DFSAdmin命令集是用來管理HDFS叢集。只有HDFS管理者才能使用這些命令。下面是一些動作/命令對的示例:

動作 命令
Put the cluster in Safemode bin/hdfs dfsadmin -safemode enter
Generate a list of DataNodes bin/hdfs dfsadmin -report
Recommission or decommission DataNode(s) bin/hdfs dfsadmin -refreshNode

瀏覽器介面

A typical HDFS install configures a web server to expose the HDFS namespace through a configurable TCP port. This allows a user to navigate the HDFS namespace and view the contents of its files using a web browser.

通常安裝HDFS時會配置一個web服務,通過一個配置好的TCP埠來暴露HDFS名稱空間。它允許使用者看到HDFS名稱空間,並能使用web瀏覽器來檢視檔案內容。

空間回收

檔案的刪除和恢復

如果垃圾配置可用,使用HDFS SHELL刪除的檔案不會立刻從HDFS刪除,而是被移動到垃圾目錄(每個使用者都有自己的垃圾目錄:/user//.Trash),檔案只要在垃圾目錄中,可以隨時進行恢復。

大部分剛刪除的檔案都被移動到垃圾目錄中(/user//.Trash/Current),並且在一個可配置的間隔時間內,HDFS為當前垃圾目錄中的檔案建立檢查點(under /user//.Trash/),同時刪除那些過期的檢查點。垃圾檢查點資訊請點選expunge command of FS shell

當回收站中的檔案過期後,Namenode會從HDFS名稱空間中刪除該檔案。檔案的刪除會導致跟該檔案相關聯的塊被釋放。需要說明的是檔案被使用者刪除的時間和對應的釋放空間的時間之間有一個明顯的時間延遲。

下面的例子將展示如何通過FS SHELL將檔案從HDFS中刪除。我們在要刪除的目錄中建立test1和test2兩個檔案

$ hadoop fs -mkdir -p delete/test1
$ hadoop fs -mkdir -p delete/test2
$ hadoop fs -ls delete/
Found 2 items
drwxr-xr-x   - hadoop hadoop          0 2015-05-08 12:39 delete/test1
drwxr-xr-x   - hadoop hadoop          0 2015-05-08 12:40 delete/test2
複製程式碼

我們將刪除test1檔案,下面的日誌顯示檔案被移動到垃圾目錄中

$ hadoop fs -rm -r delete/test1
Moved: hdfs://localhost:8020/user/hadoop/delete/test1 to trash at: hdfs://localhost:8020/user/hadoop/.Trash/Current
複製程式碼

現在我來執行將檔案刪除跳過垃圾目錄選項(skipTrash),檔案則不會轉移到垃圾目錄。檔案將完全從HDFS中移除。

$ hadoop fs -rm -r -skipTrash delete/test2
Deleted delete/test2
複製程式碼

現在在垃圾目錄中,我們只能看到test1檔案

$ hadoop fs -ls .Trash/Current/user/hadoop/delete/
Found 1 items\
drwxr-xr-x   - hadoop hadoop          0 2015-05-08 12:39 .Trash/Current/user/hadoop/delete/test1
複製程式碼

也就是test1進入垃圾目錄,而test2被永久刪除。

複製因子減少

當檔案的複製因子減小時,NameNode將在可以刪除的副本中選中多餘的副本。在下一個心跳通訊中將該資訊傳輸給DataNode。然後DataNode移除對應的資料塊並且釋放對應的空間。再重申一遍,在完成複製因子的設定和叢集中出現新的空間之間有個時間延遲。

參考

Hadoop Java API HDFS原始碼: hadoop.apache.org/version_con…

Apache Hadoop文件翻譯之一(HDFS架構)

相關文章