深入理解HDFS工做機制

  深刻理解一個技術的工做機制是靈活運用和快速解決問題的根本方法,也是惟一途徑。對於HDFS來講除了要明白它的應用場景和用法以及通用分佈式架構以外更重要的是理解關鍵步驟的原理和實現細節。在看這篇博文以前須要對HDFS以及分佈式系統有一些瞭解。請參考這篇博客。本篇博文首先對HDFS的重要特性和使用場景作一個簡要說明,以後對HDFS的數據讀寫、元數據管理以及NameNode、SecondaryNamenode的工做機制進行深刻分析。過程當中也會對一些配置參數作一個說明。html

一.HDFS的重要特性

  First. HDFS是一個文件系統,用於存儲和管理文件,經過統一的命名空間(相似於本地文件系統的目錄樹)。是分佈式的,服務器集羣中各個節點都有本身的角色和職責。node

  Then.apache

  1.HDFS中的文件在物理上是分塊存儲(block),塊的大小能夠經過配置參數( dfs.blocksize)來規定,默認大小在hadoop2.x版本中是128M,以前的版本中是64M。緩存

  2.HDFS文件系統會給客戶端提供一個統一的抽象目錄樹,客戶端經過路徑來訪問文件,形如:hdfs://namenode:port/dir-a/dir-b/dir-c/file.data安全

  3.目錄結構及文件分塊位置信息(元數據)的管理由namenode節點承擔,namenode是HDFS集羣主節點,負責維護整個hdfs文件系統的目錄樹,以及每個路徑(文件)所對應的數據塊信息(blockid及所在的datanode服務器)服務器

  4.文件的各個block的存儲管理由datanode節點承擔,datanode是HDFS集羣從節點,每個block均可以在多個datanode上存儲多個副本(副本數量也能夠經過參數設置dfs.replication,默認是3)網絡

  5.Datanode會按期向Namenode彙報自身所保存的文件block信息,而namenode則會負責保持文件的副本數量,HDFS的內部工做機制對客戶端保持透明,客戶端請求訪問HDFS都是經過向namenode申請來進行。數據結構

  6.HDFS是設計成適應一次寫入,屢次讀出的場景,且不支持文件的修改。須要頻繁的RPC交互,寫入性能很差。架構

二.HDFS寫數據分析

   1.概述負載均衡

   客戶端要向HDFS寫數據,首先要跟namenode通訊以確承認以寫文件並得到接收文件block的datanode,而後客戶端按順序將文件逐個block傳遞給相應datanode,並由接收到block的datanode負責向其餘datanode複製block的副本。

   2.寫數據步驟詳解

   

  (圖片來自網絡,僅供參考)

  1)客戶端向namenode發送上傳文件請求,namenode對要上傳目錄和文件進行檢查,判斷是否能夠上傳,並向客戶端返回檢查結果。

  2)客戶端獲得上傳文件的容許後讀取客戶端配置,若是沒有指定配置則會讀取默認配置(例如副本數和塊大小默認爲3和128M,副本是由客戶端決定的)。向namenode請求上傳一個數據塊。

  3)namenode會根據客戶端的配置來查詢datanode信息,若是使用默認配置,那麼最終結果會返回同一個機架的兩個datanode和另外一個機架的datanode。這稱爲「機架感知」策略。

  機架感知:HDFS採用一種稱爲機架感知(rack-aware)的策略來改進數據的可靠性、可用性和網絡帶寬的利用率。大型HDFS實例通常運行在跨越多個機架的計算機組成的集羣上,不一樣機架上的兩臺機器之間的通信須要通過交換機。在大多數狀況下,同一個機架內的兩臺機器間的帶寬會比不一樣機架的兩臺機器間的帶寬大。經過一個機架感知的過程,Namenode能夠肯定每一個Datanode所屬的機架id。一個簡單但沒有優化的策略就是將副本存放在不一樣的機架上。這樣能夠有效防止當整個機架失效時數據的丟失,而且容許讀數據的時候充分利用多個機架的帶寬。這種策略設置能夠將副本均勻分佈在集羣中,有利於當組件失效狀況下的負載均衡。可是,由於這種策略的一個寫操做須要傳輸數據塊到多個機架,這增長了寫的代價。在大多數狀況下,副本系數是3,HDFS的存放策略是將一個副本存放在本地機架的節點上,一個副本放在同一機架的另外一個節點上,最後一個副本放在不一樣機架的節點上。這種策略減小了機架間的數據傳輸,這就提升了寫操做的效率。機架的錯誤遠遠比節點的錯誤少,因此這個策略不會影響到數據的可靠性和可用性。於此同時,由於數據塊只放在兩個(不是三個)不一樣的機架上,因此此策略減小了讀取數據時須要的網絡傳輸總帶寬。在這種策略下,副本並非均勻分佈在不一樣的機架上。三分之一的副本在一個節點上,三分之二的副本在一個機架上,其餘副本均勻分佈在剩下的機架中,這一策略在不損害數據可靠性和讀取性能的狀況下改進了寫的性能。

  4)客戶端在開始傳輸數據塊以前會把數據緩存在本地,當緩存大小超過了一個數據塊的大小,客戶端就會從namenode獲取要上傳的datanode列表。以後會在客戶端和第一個datanode創建鏈接開始流式的傳輸數據,這個datanode會一小部分一小部分(4K)的接收數據而後寫入本地倉庫,同時會把這些數據傳輸到第二個datanode,第二個datanode也一樣一小部分一小部分的接收數據並寫入本地倉庫,同時傳輸給第三個datanode,依次類推。這樣逐級調用和返回以後,待這個數據塊傳輸完成客戶端後告訴namenode數據塊傳輸完成,這時候namenode纔會更新元數據信息記錄操做日誌。

  5)第一個數據塊傳輸完成後會使用一樣的方式傳輸下面的數據塊直到整個文件上傳完成。

  細節:

  a.請求和應答是使用RPC的方式,客戶端經過ClientProtocol與namenode通訊,namenode和datanode之間使用DatanodeProtocol交互。在設計上,namenode不會主動發起RPC,而是響應來自客戶端或 datanode 的RPC請求。客戶端和datanode之間是使用socket進行數據傳輸,和namenode之間的交互採用nio封裝的RPC。

  b.HDFS有本身的序列化協議。

  c.在數據塊傳輸成功後但客戶端沒有告訴namenode以前若是namenode宕機那麼這個數據塊就會丟失。

  d.在流式複製時,逐級傳輸和響應採用響應隊列來等待傳輸結果。隊列響應完成後返回給客戶端。

  c.在流式複製時若是有一臺或兩臺(不是所有)沒有複製成功,不影響最後結果,只不過datanode會按期向namenode彙報自身信息。若是發現異常namenode會指揮datanode刪除殘餘數據和完善副本。若是副本數量少於某個最小值就會進入安全模式。

安全模式:Namenode啓動後會進入一個稱爲安全模式的特殊狀態。處於安全模式的Namenode是不會進行數據塊的複製的。Namenode從全部的 Datanode接收心跳信號和塊狀態報告。塊狀態報告包括了某個Datanode全部的數據塊列表。每一個數據塊都有一個指定的最小副本數。當Namenode檢測確認某個數據塊的副本數目達到這個最小值,那麼該數據塊就會被認爲是副本安全(safely replicated)的;在必定百分比(這個參數可配置)的數據塊被Namenode檢測確認是安全以後(加上一個額外的30秒等待時間),Namenode將退出安全模式狀態。接下來它會肯定還有哪些數據塊的副本沒有達到指定數目,並將這些數據塊複製到其餘Datanode上。

 三.HDFS讀數據分析

   1.概述

   客戶端將要讀取的文件路徑發送給namenode,namenode獲取文件的元信息(主要是block的存放位置信息)返回給客戶端,客戶端根據返回的信息找到相應datanode逐個獲取文件的block並在客戶端本地進行數據追加合併從而得到整個文件。

  2.讀數據步驟詳解

   

  (圖片來源於網絡,僅供參考)

  1)客戶端向namenode發起RPC調用,請求讀取文件數據。

  2)namenode檢查文件是否存在,若是存在則獲取文件的元信息(blockid以及對應的datanode列表)。

  3)客戶端收到元信息後選取一個網絡距離最近的datanode,依次請求讀取每一個數據塊。客戶端首先要校檢文件是否損壞,若是損壞,客戶端會選取另外的datanode請求。

  4)datanode與客戶端簡歷socket鏈接,傳輸對應的數據塊,客戶端收到數據緩存到本地,以後寫入文件。

  5)依次傳輸剩下的數據塊,直到整個文件合併完成。

從某個Datanode獲取的數據塊有多是損壞的,損壞多是由Datanode的存儲設備錯誤、網絡錯誤或者軟件bug形成的。HDFS客戶端軟件實現了對HDFS文件內容的校驗和(checksum)檢查。當客戶端建立一個新的HDFS文件,會計算這個文件每一個數據塊的校驗和,並將校驗和做爲一個單獨的隱藏文件保存在同一個HDFS名字空間下。當客戶端獲取文件內容後,它會檢驗從Datanode獲取的數據跟相應的校驗和文件中的校驗和是否匹配,若是不匹配,客戶端能夠選擇從其餘Datanode獲取該數據塊的副本。

四.HDFS刪除數據分析

   HDFS刪除數據比較流程相對簡單,只列出詳細步驟:

  1)客戶端向namenode發起RPC調用,請求刪除文件。namenode檢查合法性。

  2)namenode查詢文件相關元信息,向存儲文件數據塊的datanode發出刪除請求。

  3)datanode刪除相關數據塊。返回結果。

  4)namenode返回結果給客戶端。

  當用戶或應用程序刪除某個文件時,這個文件並無馬上從HDFS中刪除。實際上,HDFS會將這個文件重命名轉移到/trash目錄。只要文件還在/trash目錄中,該文件就能夠被迅速地恢復。文件在/trash中保存的時間是可配置的,當超過這個時間時,Namenode就會將該文件從名字空間中刪除。刪除文件會使得該文件相關的數據塊被釋放。注意,從用戶刪除文件到HDFS空閒空間的增長之間會有必定時間的延遲。只要被刪除的文件還在/trash目錄中,用戶就能夠恢復這個文件。若是用戶想恢復被刪除的文件,他/她能夠瀏覽/trash目錄找回該文件。/trash目錄僅僅保存被刪除文件的最後副本。/trash目錄與其餘的目錄沒有什麼區別,除了一點:在該目錄上HDFS會應用一個特殊策略來自動刪除文件。目前的默認策略是刪除/trash中保留時間超過6小時的文件。未來,這個策略能夠經過一個被良好定義的接口配置。

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

 五.NameNode元數據管理原理分析

   1.概述

  首先明確namenode的職責:響應客戶端請求、管理元數據。

  namenode對元數據有三種存儲方式:

  內存元數據(NameSystem)

  磁盤元數據鏡像文件

  數據操做日誌文件(可經過日誌運算出元數據)

  細節:HDFS不適合存儲小文件的緣由,每一個文件都會產生元信息,當小文件多了以後元信息也就多了,對namenode會形成壓力。

  2.對三種存儲機制的進一步解釋

  內存元數據就是當前namenode正在使用的元數據,是存儲在內存中的。

  磁盤元數據鏡像文件是內存元數據的鏡像,保存在namenode工做目錄中,它是一個準元數據,做用是在namenode宕機時可以快速較準確的恢復元數據。稱爲fsimage。

  數據操做日誌文件是用來記錄元數據操做的,在每次改動元數據時都會追加日誌記錄,若是有完整的日誌就能夠還原完整的元數據。主要做用是用來完善fsimage,減小fsimage和內存元數據的差距。稱爲editslog。

  3.checkpoint機制分析

  由於namenode自己的任務就很是重要,爲了避免再給namenode壓力,日誌合併到fsimage就引入了另外一個角色secondarynamenode。secondarynamenode負責按期把editslog合併到fsimage,「按期」是namenode向secondarynamenode發送RPC請求的,是按時間或者日誌記錄條數爲「間隔」的,這樣即不會浪費合併操做又不會形成fsimage和內存元數據有很大的差距。由於元數據的改變頻率是不固定的。

  每隔一段時間,會由secondary namenode將namenode上積累的全部edits和一個最新的fsimage下載到本地,並加載到內存進行merge(這個過程稱爲checkpoint)。

  

  (圖片來源於網絡,僅供參考)

  1)namenode向secondarynamenode發送RPC請求,請求合併editslog到fsimage。

  2)secondarynamenode收到請求後從namenode上讀取(經過http服務)editslog(多個,滾動日誌文件)和fsimage文件。

  3)secondarynamenode會根據拿到的editslog合併到fsimage。造成最新的fsimage文件。(中間有不少步驟,把文件加載到內存,還原成元數據結構,合併,再生成文件,新生成的文件名爲fsimage.checkpoint)。

  4)secondarynamenode經過http服務把fsimage.checkpoint文件上傳到namenode,而且經過RPC調用把文件更名爲fsimage。

  namenode和secondary namenode的工做目錄存儲結構徹底相同,因此,當namenode故障退出須要從新恢復時,能夠從secondary namenode的工做目錄中將fsimage拷貝到namenode的工做目錄,以恢復namenode的元數據。

  關於checkpoint操做的配置:

dfs.namenode.checkpoint.check.period=60  #檢查觸發條件是否知足的頻率,60秒

dfs.namenode.checkpoint.dir=file://${hadoop.tmp.dir}/dfs/namesecondary

#以上兩個參數作checkpoint操做時,secondary namenode的本地工做目錄

dfs.namenode.checkpoint.edits.dir=${dfs.namenode.checkpoint.dir}

dfs.namenode.checkpoint.max-retries=3  #最大重試次數

dfs.namenode.checkpoint.period=3600  #兩次checkpoint之間的時間間隔3600秒

dfs.namenode.checkpoint.txns=1000000 #兩次checkpoint之間最大的操做記錄

  editslog和fsimage文件存儲在$dfs.namenode.name.dir/current目錄下,這個目錄能夠在hdfs-site.xml中配置的。這個目錄下的文件結構以下:

  

   包括edits日誌文件(滾動的多個文件),有一個是edits_inprogress_*是當前正在寫的日誌。fsimage文件以及md5校檢文件。seen_txid是記錄當前滾動序號,表明seen_txid以前的日誌都已經合併完成。 

  $dfs.namenode.name.dir/current/seen_txid很是重要,是存放transactionId的文件,format以後是0,它表明的是namenode裏面的edits_*文件的尾數,namenode重啓的時候,會按照seen_txid的數字恢復。因此當你的hdfs發生異常重啓的時候,必定要比對seen_txid內的數字是否是你edits最後的尾數,否則會發生重啓namenode時metaData的資料有缺乏,致使誤刪Datanode上多餘Block的信息。

 六.總結

   深刻理解了以上介紹的工做機制就能夠嘗試運用他們解決工做和學習中遇到的問題了,只要真正理解了核心原理,全部問題均可以本身找到答案。就是要不斷的學習、實踐、總結,再學習、再實踐、再總結。這樣才能紮紮實實作的出色。共勉。

  接下來會有一篇HDFS常見問題的總結。

 參考資料:http://hadoop.apache.org/docs/stable2/hadoop-project-dist/hadoop-hdfs/HdfsUserGuide.html

相關文章
相關標籤/搜索