1. 程式人生 > >Hadoop架構和設計要點

Hadoop架構和設計要點

一、前提和設計目標

1、硬體錯誤是常態,而非異常情況,HDFS可能是有成百上千的server組成,任何一個元件都有可能一直失效,因此錯誤檢測和快速、自動的恢復是HDFS的核心架構目標。

2、跑在HDFS上的應用與一般的應用不同,它們主要是以流式讀為主,做批量處理;比之關注資料訪問的低延遲問題,更關鍵的在於資料訪問的高吞吐量。

3、HDFS以支援大資料集合為目標,一個儲存在上面的典型檔案大小一般都在千兆至T位元組,一個單一HDFS例項應該能支撐數以千萬計的檔案。

4、 HDFS應用對檔案要求的是write-one-read-many訪問模型。一個檔案經過建立、寫,關閉之後就不需要改變。這一假設簡化了資料一致性問題,使高吞吐量的資料訪問成為可能。典型的如MapReduce框架,或者一個web crawler應用都很適合這個模型。

5、移動計算的代價比之移動資料的代價低。一個應用請求的計算,離它操作的資料越近就越高效,這在資料達到海量級別的時候更是如此。將計算移動到資料附近,比之將資料移動到應用所在顯然更好,HDFS提供給應用這樣的介面。

6、在異構的軟硬體平臺間的可移植性。

二、Namenode和Datanode

HDFS採用master/slave架構。一個HDFS叢集是有一個Namenode和一定數目的Datanode組成。Namenode是一箇中心伺服器,負責管理檔案系統的namespace和客戶端對檔案的訪問。Datanode在叢集中一般是一個節點一個,負責管理節點上它們附帶的儲存。在內部,一個檔案其實分成一個或多個block,這些block儲存在Datanode集合裡。Namenode執行檔案系統的namespace操作,例如開啟、關閉、重新命名檔案和目錄,同時決定block到具體Datanode節點的對映。Datanode在Namenode的指揮下進行block的建立、刪除和複製。Namenode和Datanode都是設計成可以跑在普通的廉價的執行linux的機器上。HDFS採用java語言開發,因此可以部署在很大範圍的機器上。一個典型的部署場景是一臺機器跑一個單獨的Namenode節點,叢集中的其他機器各跑一個Datanode例項。這個架構並不排除一臺機器上跑多個Datanode,不過這比較少見。

單一節點的Namenode大大簡化了系統的架構。Namenode負責保管和管理所有的HDFS元資料,因而使用者資料就不需要通過Namenode(也就是說檔案資料的讀寫是直接在Datanode上)。

三、檔案系統的namespace

HDFS支援傳統的層次型檔案組織,與大多數其他檔案系統類似,使用者可以建立目錄,並在其間建立、刪除、移動和重新命名檔案。HDFS不支援user quotas和訪問許可權,也不支援連結(link),不過當前的架構並不排除實現這些特性。Namenode維護檔案系統的namespace,任何對檔案系統namespace和檔案屬性的修改都將被Namenode記錄下來。應用可以設定HDFS儲存的檔案的副本數目,檔案副本的數目稱為檔案的 replication因子,這個資訊也是由Namenode儲存。

四、資料複製

HDFS被設計成在一個大叢集中可以跨機器地可靠地儲存海量的檔案。它將每個檔案儲存成block序列,除了最後一個block,所有的block都是同樣的大小。檔案的所有block為了容錯都會被複制。每個檔案的block大小和replication因子都是可配置的。Replication因子可以在檔案建立的時候配置,以後也可以改變。HDFS中的檔案是write-one,並且嚴格要求在任何時候只有一個writer。Namenode全權管理block的複製,它週期性地從叢集中的每個Datanode接收心跳包和一個Blockreport。心跳包的接收表示該Datanode節點正常工作,而Blockreport包括了該Datanode上所有的block組成的列表。

1、副本的存放,副本的存放是HDFS可靠性和效能的關鍵。HDFS採用一種稱為rack-aware的策略來改進資料的可靠性、有效性和網路頻寬的利用。這個策略實現的短期目標是驗證在生產環境下的表現,觀察它的行為,構建測試和研究的基礎,以便實現更先進的策略。龐大的HDFS例項一般執行在多個機架的計算機形成的叢集上,不同機架間的兩臺機器的通訊需要通過交換機,顯然通常情況下,同一個機架內的兩個節點間的頻寬會比不同機架間的兩臺機器的頻寬大。

通過一個稱為Rack Awareness的過程,Namenode決定了每個Datanode所屬的rack id。一個簡單但沒有優化的策略就是將副本存放在單獨的機架上。這樣可以防止整個機架(非副本存放)失效的情況,並且允許讀資料的時候可以從多個機架讀取。這個簡單策略設定可以將副本分佈在叢集中,有利於元件失敗情況下的負載均衡。但是,這個簡單策略加大了寫的代價,因為一個寫操作需要傳輸block到多個機架。

在大多數情況下,replication因子是3,HDFS的存放策略是將一個副本存放在本地機架上的節點,一個副本放在同一機架上的另一個節點,最後一個副本放在不同機架上的一個節點。機架的錯誤遠遠比節點的錯誤少,這個策略不會影響到資料的可靠性和有效性。三分之一的副本在一個節點上,三分之二在一個機架上,其他儲存在剩下的機架中,這一策略改進了寫的效能。

2、副本的選擇,為了降低整體的頻寬消耗和讀延時,HDFS會盡量讓reader讀最近的副本。如果在reader的同一個機架上有一個副本,那麼就讀該副本。如果一個HDFS叢集跨越多個數據中心,那麼reader也將首先嚐試讀本地資料中心的副本。

3、SafeMode

Namenode啟動後會進入一個稱為SafeMode的特殊狀態,處在這個狀態的Namenode是不會進行資料塊的複製的。Namenode從所有的 Datanode接收心跳包和Blockreport。Blockreport包括了某個Datanode所有的資料塊列表。每個block都有指定的最小數目的副本。當Namenode檢測確認某個Datanode的資料塊副本的最小數目,那麼該Datanode就會被認為是安全的;如果一定百分比(這個引數可配置)的資料塊檢測確認是安全的,那麼Namenode將退出SafeMode狀態,接下來它會確定還有哪些資料塊的副本沒有達到指定數目,並將這些block複製到其他Datanode。

五、檔案系統元資料的持久化

Namenode儲存HDFS的元資料。對於任何對檔案元資料產生修改的操作,Namenode都使用一個稱為Editlog的事務日誌記錄下來。例如,在HDFS中建立一個檔案,Namenode就會在Editlog中插入一條記錄來表示;同樣,修改檔案的replication因子也將往 Editlog插入一條記錄。Namenode在本地OS的檔案系統中儲存這個Editlog。整個檔案系統的namespace,包括block到檔案的對映、檔案的屬性,都儲存在稱為FsImage的檔案中,這個檔案也是放在Namenode所在系統的檔案系統上。

Namenode在記憶體中儲存著整個檔案系統namespace和檔案Blockmap的映像。這個關鍵的元資料設計得很緊湊,因而一個帶有4G記憶體的 Namenode足夠支撐海量的檔案和目錄。當Namenode啟動時,它從硬碟中讀取Editlog和FsImage,將所有Editlog中的事務作用(apply)在記憶體中的FsImage ,並將這個新版本的FsImage從記憶體中flush到硬碟上,然後再truncate這個舊的Editlog,因為這個舊的Editlog的事務都已經作用在FsImage上了。這個過程稱為checkpoint。在當前實現中,checkpoint只發生在Namenode啟動時,在不久的將來我們將實現支援週期性的checkpoint。

Datanode並不知道關於檔案的任何東西,除了將檔案中的資料儲存在本地的檔案系統上。它把每個HDFS資料塊儲存在本地檔案系統上隔離的檔案中。 Datanode並不在同一個目錄建立所有的檔案,相反,它用啟發式地方法來確定每個目錄的最佳檔案數目,並且在適當的時候建立子目錄。在同一個目錄建立所有的檔案不是最優的選擇,因為本地檔案系統可能無法高效地在單一目錄中支援大量的檔案。當一個Datanode啟動時,它掃描本地檔案系統,對這些本地檔案產生相應的一個所有HDFS資料塊的列表,然後傳送報告到Namenode,這個報告就是Blockreport。

六、通訊協議

所有的HDFS通訊協議都是構建在TCP/IP協議上。客戶端通過一個可配置的埠連線到Namenode,通過ClientProtocol與 Namenode互動。而Datanode是使用DatanodeProtocol與Namenode互動。從ClientProtocol和 Datanodeprotocol抽象出一個遠端呼叫(RPC),在設計上,Namenode不會主動發起RPC,而是是響應來自客戶端和 Datanode 的RPC請求。

七、健壯性

HDFS的主要目標就是實現在失敗情況下的資料儲存可靠性。常見的三種失敗:Namenode failures, Datanode failures和網路分割(network partitions)。

1、硬碟資料錯誤、心跳檢測和重新複製

每個Datanode節點都向Namenode週期性地傳送心跳包。網路切割可能導致一部分Datanode跟Namenode失去聯絡。 Namenode通過心跳包的缺失檢測到這一情況,並將這些Datanode標記為dead,不會將新的IO請求發給它們。寄存在dead Datanode上的任何資料將不再有效。Datanode的死亡可能引起一些block的副本數目低於指定值,Namenode不斷地跟蹤需要複製的 block,在任何需要的情況下啟動複製。在下列情況可能需要重新複製:某個Datanode節點失效,某個副本遭到損壞,Datanode上的硬碟錯誤,或者檔案的replication因子增大。

2、叢集均衡

HDFS支援資料的均衡計劃,如果某個Datanode節點上的空閒空間低於特定的臨界點,那麼就會啟動一個計劃自動地將資料從一個Datanode搬移到空閒的Datanode。當對某個檔案的請求突然增加,那麼也可能啟動一個計劃建立該檔案新的副本,並分佈到叢集中以滿足應用的要求。這些均衡計劃目前還沒有實現。

3、資料完整性

從某個Datanode獲取的資料塊有可能是損壞的,這個損壞可能是由於Datanode的儲存裝置錯誤、網路錯誤或者軟體bug造成的。HDFS客戶端軟體實現了HDFS檔案內容的校驗和。當某個客戶端建立一個新的HDFS檔案,會計算這個檔案每個block的校驗和,並作為一個單獨的隱藏檔案儲存這些校驗和在同一個HDFS namespace下。當客戶端檢索檔案內容,它會確認從Datanode獲取的資料跟相應的校驗和檔案中的校驗和是否匹配,如果不匹配,客戶端可以選擇從其他Datanode獲取該block的副本。

4、元資料磁碟錯誤

FsImage和Editlog是HDFS的核心資料結構。這些檔案如果損壞了,整個HDFS例項都將失效。因而,Namenode可以配置成支援維護多個FsImage和Editlog的拷貝。任何對FsImage或者Editlog的修改,都將同步到它們的副本上。這個同步操作可能會降低 Namenode每秒能支援處理的namespace事務。這個代價是可以接受的,因為HDFS是資料密集的,而非元資料密集。當Namenode重啟的時候,它總是選取最近的一致的FsImage和Editlog使用。

Namenode在HDFS是單點存在,如果Namenode所在的機器錯誤,手工的干預是必須的。目前,在另一臺機器上重啟因故障而停止服務的Namenode這個功能還沒實現。

5、快照

快照支援某個時間的資料拷貝,當HDFS資料損壞的時候,可以恢復到過去一個已知正確的時間點。HDFS目前還不支援快照功能。

八、資料組織

1、資料塊

相容HDFS的應用都是處理大資料集合的。這些應用都是寫資料一次,讀卻是一次到多次,並且讀的速度要滿足流式讀。HDFS支援檔案的write- once-read-many語義。一個典型的block大小是64MB,因而,檔案總是按照64M切分成chunk,每個chunk儲存於不同的 Datanode

2、步驟

某個客戶端建立檔案的請求其實並沒有立即發給Namenode,事實上,HDFS客戶端會將檔案資料快取到本地的一個臨時檔案。應用的寫被透明地重定向到這個臨時檔案。當這個臨時檔案累積的資料超過一個block的大小(預設64M),客戶端才會聯絡Namenode。Namenode將檔名插入檔案系統的層次結構中,並且分配一個數據塊給它,然後返回Datanode的識別符號和目標資料塊給客戶端。客戶端將本地臨時檔案flush到指定的 Datanode上。當檔案關閉時,在臨時檔案中剩餘的沒有flush的資料也會傳輸到指定的Datanode,然後客戶端告訴Namenode檔案已經關閉。此時Namenode才將檔案建立操作提交到持久儲存。如果Namenode在檔案關閉前掛了,該檔案將丟失。

上述方法是對通過對HDFS上執行的目標應用認真考慮的結果。如果不採用客戶端快取,由於網路速度和網路堵塞會對吞估量造成比較大的影響。

3、流水線複製

當某個客戶端向HDFS檔案寫資料的時候,一開始是寫入本地臨時檔案,假設該檔案的replication因子設定為3,那麼客戶端會從Namenode 獲取一張Datanode列表來存放副本。然後客戶端開始向第一個Datanode傳輸資料,第一個Datanode一小部分一小部分(4kb)地接收資料,將每個部分寫入本地倉庫,並且同時傳輸該部分到第二個Datanode節點。第二個Datanode也是這樣,邊收邊傳,一小部分一小部分地收,儲存在本地倉庫,同時傳給第三個Datanode,第三個Datanode就僅僅是接收並存儲了。這就是流水線式的複製。

九、可訪問性

HDFS給應用提供了多種訪問方式,可以通過DFSShell通過命令列與HDFS資料進行互動,可以通過java API呼叫,也可以通過C語言的封裝API訪問,並且提供了瀏覽器訪問的方式。正在開發通過WebDav協議訪問的方式。具體使用參考文件。

十、空間的回收

1、檔案的刪除和恢復

使用者或者應用刪除某個檔案,這個檔案並沒有立刻從HDFS中刪除。相反,HDFS將這個檔案重新命名,並轉移到/trash目錄。當檔案還在/trash目錄時,該檔案可以被迅速地恢復。檔案在/trash中儲存的時間是可配置的,當超過這個時間,Namenode就會將該檔案從namespace中刪除。檔案的刪除,也將釋放關聯該檔案的資料塊。注意到,在檔案被使用者刪除和HDFS空閒空間的增加之間會有一個等待時間延遲。

當被刪除的檔案還保留在/trash目錄中的時候,如果使用者想恢復這個檔案,可以檢索瀏覽/trash目錄並檢索該檔案。/trash目錄僅僅儲存被刪除檔案的最近一次拷貝。/trash目錄與其他檔案目錄沒有什麼不同,除了一點:HDFS在該目錄上應用了一個特殊的策略來自動刪除檔案,目前的預設策略是刪除保留超過6小時的檔案,這個策略以後會定義成可配置的介面。

2、Replication因子的減小

當某個檔案的replication因子減小,Namenode會選擇要刪除的過剩的副本。下次心跳檢測就將該資訊傳遞給Datanode, Datanode就會移除相應的block並釋放空間,同樣,在呼叫setReplication方法和叢集中的空閒空間增加之間會有一個時間延遲。

參考資料: