1. 程式人生 > >Hadoop基礎 - Hadoop核心元件之HDFS工作原理

Hadoop基礎 - Hadoop核心元件之HDFS工作原理

HDFS

1.HDFS是Hadoop的儲存元件是一個檔案系統,用於儲存和管理檔案,通過統一的名稱空間(類似於本地檔案系統的目錄樹)。是分散式的,伺服器叢集中各個節點都有自己的角色和職責。HDFS為高吞吐量做了優化,尤其在讀寫大檔案(GB級別或更大)時執行最佳。為了維持高吞吐量,HDFS利用超大資料塊和資料區域性性優化來減少網路輸入/輸出(I/O)

2.HDFS的主要特性還有擴充套件性和可用性,部分功能是依靠資料複製和容錯來實現的。HDFS按照配置的副本數複製檔案,它能夠容忍硬體及軟體錯誤,且能夠自動沖洗複製壞點上的資料塊

3.HDFS中的檔案在物理上是分塊儲存(block),塊的大小可以通過配置引數( dfs.blocksize)來規定,預設大小在hadoop2.x版本中是128M,之前的版本中是64M

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

5.目錄結構及檔案分塊位置資訊(元資料)的管理由namenode節點承擔,namenode是HDFS叢集主節點,負責維護整個hdfs檔案系統的目錄樹,以及每一個路徑(檔案)所對應的資料塊資訊(blockid及所在的datanode伺服器)

6.檔案的各個block的儲存管理由datanode節點承擔,datanode是HDFS叢集從節點,每一個block都可以在多個datanode上儲存多個副本(副本數量也可以通過引數設定dfs.replication,預設是3)

7.Datanode會定期向Namenode彙報自身所儲存的檔案block資訊,而namenode則會負責保持檔案的副本數量,HDFS的內部工作機制對客戶端保持透明,客戶端請求訪問HDFS都是通過向namenode申請來進行。

8.HDFS是設計成適應一次寫入,多次讀出的場景,且不支援檔案的修改。需要頻繁的RPC互動,寫入效能不好

1 、HDFS寫資料

客戶端要向HDFS寫資料,首先要跟namenode通訊以確認可以寫檔案並獲得接收檔案block的datanode,然後客戶端按順序將檔案逐個block傳遞給相應datanode,並由接收到block的datanode負責向其他datanode複製block的副本。

  1. 1.客戶端向namenode傳送上傳檔案請求,namenode對要上傳目錄和檔案進行檢查,判斷是否可以上傳,並向客戶端返回檢查結果。
  2. 2.客戶端得到上傳檔案的允許後讀取客戶端配置,如果沒有指定配置則會讀取預設配置(例如副本數和塊大小預設為3和128M,副本是由客戶端決定的)。向namenode請求上傳一個數據塊。
  3. 3.namenode會根據客戶端的配置來查詢datanode資訊,如果使用預設配置,那麼最終結果會返回同一個機架的兩個datanode和另一個機架的datanode。這稱為“機架感知”策略。
  4. 4.客戶端在開始傳輸資料塊之前會把資料快取在本地,當快取大小超過了一個數據塊的大小,客戶端就會從namenode獲取要上傳的datanode列表。之後會在客戶端和第一個datanode建立連線開始流式的傳輸資料,這個datanode會一小部分一小部分(4K)的接收資料然後寫入本地倉庫,同時會把這些資料傳輸到第二個datanode,第二個datanode也同樣一小部分一小部分的接收資料並寫入本地倉庫,同時傳輸給第三個datanode,依次類推。這樣逐級呼叫和返回之後,待這個資料塊傳輸完成客戶端後告訴namenode資料塊傳輸完成,這時候namenode才會更新元資料資訊記錄操作日誌。
  5. 5.第一個資料塊傳輸完成後會使用同樣的方式傳輸下面的資料塊直到整個檔案上傳完成。

機架感知:HDFS採用一種稱為機架感知(rack-aware)的策略來改進資料的可靠性、可用性和網路頻寬的利用率。大型HDFS例項一般執行在跨越多個機架的計算機組成的叢集上,不同機架上的兩臺機器之間的通訊需要經過交換機。在大多數情況下,同一個機架內的兩臺機器間的頻寬會比不同機架的兩臺機器間的頻寬大。通過一個機架感知的過程,Namenode可以確定每個Datanode所屬的機架id。一個簡單但沒有優化的策略就是將副本存放在不同的機架上。這樣可以有效防止當整個機架失效時資料的丟失,並且允許讀資料的時候充分利用多個機架的頻寬。這種策略設定可以將副本均勻分佈在叢集中,有利於當元件失效情況下的負載均衡。但是,因為這種策略的一個寫操作需要傳輸資料塊到多個機架,這增加了寫的代價。在大多數情況下,副本系數是3,HDFS的存放策略是將一個副本存放在本地機架的節點上,一個副本放在同一機架的另一個節點上,最後一個副本放在不同機架的節點上。這種策略減少了機架間的資料傳輸,這就提高了寫操作的效率。機架的錯誤遠遠比節點的錯誤少,所以這個策略不會影響到資料的可靠性和可用性。於此同時,因為資料塊只放在兩個(不是三個)不同的機架上,所以此策略減少了讀取資料時需要的網路傳輸總頻寬。在這種策略下,副本並不是均勻分佈在不同的機架上。三分之一的副本在一個節點上,三分之二的副本在一個機架上,其他副本均勻分佈在剩下的機架中,這一策略在不損害資料可靠性和讀取效能的情況下改進了寫的效能。

具體的操作細節:

  1. 請求和應答是使用RPC的方式,客戶端通過ClientProtocol與namenode通訊,namenode和datanode之間使用DatanodeProtocol互動。在設計上,namenode不會主動發起RPC,而是響應來自客戶端或datanode的RPC請求。客戶端和datanode之間是使用socket進行資料傳輸,和namenode之間的互動採用nio封裝的RPC。
  2. HDFS有自己的序列化協議。
  3. 在資料塊傳輸成功後但客戶端沒有告訴namenode之前如果namenode宕機那麼這個資料塊就會丟失。
  4. 在流式複製時如果有一臺或兩臺(不是全部)沒有複製成功,不影響最後結果,只不過datanode會定期向namenode彙報自身資訊。如果發現異常namenode會指揮datanode刪除殘餘資料和完善副本。如果副本數量少於某個最小值就會進入安全模式。

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

2、 HDFS讀資料

  1. 1.客戶端向namenode發起RPC呼叫,請求讀取檔案資料。
  2. 2.namenode檢查檔案是否存在,如果存在則獲取檔案的元資訊(blockid以及對應的datanode列表)。
  3. 3.客戶端收到元資訊後選取一個網路距離最近的datanode,依次請求讀取每個資料塊。客戶端首先要校檢檔案是否損壞,如果損壞,客戶端會選取另外的datanode請求。
  4. 4.datanode與客戶端建立socket連線,傳輸對應的資料塊,客戶端收到資料快取到本地,之後寫入檔案。
  5. 5.依次傳輸剩下的資料塊,直到整個檔案合併完成。

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

3、 HDFS刪除資料

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

  1. 1.客戶端向namenode發起RPC呼叫,請求刪除檔案。namenode檢查合法性。
  2. 2.namenode查詢檔案相關元資訊,向儲存檔案資料塊的datanode發出刪除請求。
  3. 3.datanode刪除相關資料塊。返回結果。
  4. 4.namenode返回結果給客戶端。


當用戶或應用程式刪除某個檔案時,這個檔案並沒有立刻從HDFS中刪除。實際上,HDFS會將這個檔案重新命名轉移到/trash目錄。只要檔案還在/trash目錄中,該檔案就可以被迅速地恢復。檔案在/trash中儲存的時間是可配置的,當超過這個時間時,Namenode就會將該檔案從名字空間中刪除。刪除檔案會使得該檔案相關的資料塊被釋放。注意,從使用者刪除檔案到HDFS空閒空間的增加之間會有一定時間的延遲。只要被刪除的檔案還在/trash目錄中,使用者就可以恢復這個檔案。如果使用者想恢復被刪除的檔案,可以瀏覽/trash目錄找回該檔案。/trash目錄僅僅儲存被刪除檔案的最後副本。/trash目錄與其他的目錄沒有什麼區別,除了一點:在該目錄上HDFS會應用一個特殊策略來自動刪除檔案。目前的預設策略是刪除/trash中保留時間超過6小時的檔案。將來,這個策略可以通過一個被良好定義的介面配置。

當一個檔案的副本系數被減小後,Namenode會選擇過剩的副本刪除。下次心跳檢測時會將該資訊傳遞給Datanode。Datanode隨機移除相應的資料塊,叢集中的空閒空間加大。同樣,在呼叫setReplication API結束和叢集中空閒空間增加間會有一定的延遲。

4、NameNode元資料管理

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

namenode對元資料有三種儲存方式:

  • 記憶體元資料(NameSystem)【記憶體元資料就是當前namenode正在使用的元資料,是儲存在記憶體中的。】
  • 磁碟元資料映象檔案【磁碟元資料映象檔案是記憶體元資料的映象,儲存在namenode工作目錄中,它是一個準元資料,作用是在namenode宕機時能夠快速較準確的恢復元資料。稱為fsimage。】
  • 資料操作日誌檔案(可通過日誌運算出元資料)【資料操作日誌檔案是用來記錄元資料操作的,在每次改動元資料時都會追加日誌記錄,如果有完整的日誌就可以還原完整的元資料。主要作用是用來完善fsimage,減少fsimage和記憶體元資料的差距。稱為editslog。】

細節:HDFS不適合儲存小檔案的原因,每個檔案都會產生元資訊,當小檔案多了之後元資訊也就多了,對namenode會造成壓力。

checkpoint機制

因為namenode本身的任務就非常重要,為了不再給namenode壓力,日誌合併到fsimage就引入了另一個角色secondarynamenode。secondarynamenode負責定期把editslog合併到fsimage,“定期”是namenode向secondarynamenode傳送RPC請求的,是按時間或者日誌記錄條數為“間隔”的,這樣即不會浪費合併操作又不會造成fsimage和記憶體元資料有很大的差距。因為元資料的改變頻率是不固定的。

每隔一段時間,會由secondarynamenode將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。
  5. namenode和secondary namenode的工作目錄儲存結構完全相同,所以,當namenode故障退出需要重新恢復時,可以從secondarynamenode的工作目錄中將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的資訊。

Hadoop2.x中HDFS的改進

在Hadoop1.x中,名稱節點會引發系統單點故障,因為只有NameNode。如果執行NN的伺服器出現了故障,那麼整個叢集就處於不可用狀態。
除非NN在另一個節點上重啟。除了單點故障這個問題,在叢集需要維護的情況下,NN需要重啟,那麼在NN恢復正常之前,整個叢集也是處於不可用狀態。

Hadoop2.x中引入了高可用NN(High Availability NameNode),其實現的核心思想是:使用兩個相同的NM,

  • 一個處於活動狀態(active mode):為系統提供服務
  • 另一個處於待機狀態(standby mode):實時同步活動節點的資料,一旦活動節點宕機,系統可快速進行故障切換
  • 為了實現這個設計,2個NN必須共享同一個檔案儲存裝置(NFS)。在活動節點上的任何修改都會記錄到共享儲存裝置的edits日誌檔案中。待機狀態的NN將這些修改應用到自己的名稱空間中。

一旦活動NN出現故障,待機NN中的資料都被應用,來接管活動NN。

注意點:
名稱節點儲存的元資料中不包括資料塊的儲存位置(這些資訊是在NN啟動的時候通過心跳機制獲得的),為了保證NN的快速切換,DataNode需要知道2個NN的位置,並在啟動的時候箱2個NN都發送資訊,所以心跳都是2個NN同時進行

原文:https://blog.csdn.net/wee_mita/article/details/72676155