該系列總覽: Hadoop3.1.1架構體系——設計原理闡述與Client源碼圖文詳解 : 總覽
首先,我們要提出HDFS存儲特點:
1.高容錯
2.一個文件被切成塊(新版本默認128MB一個塊)在不同的DataNode存儲
3.客戶端通過流水線,在NameNode的調節下,將數據以Packet的形式流式地輸送到流水線上
如果不清楚NameNode,DataNode等概念請先閱讀HDFS架構文檔: Hadoop架構中文文檔
為了確保上述這些特點,HDFS對塊的狀態進行了定義,以控制數據塊在傳輸過程中的有效性。
在NameNode看來,塊(Block)主要有以下4種狀態。
1.UNDER_CONSTRUCTION
2.UNDER_RECOVERY
3.COMMITED
4.COMPLETED
在DataNode看來,塊(Block)應該稱為“備份 (Replica)”比較合適,在DataNode種,備份主要有以下幾種狀態
1.RBW (Replica Begin Written)
2.RWR (Replica Waiting To Be Recovered)
3.RUR (Replica Under Recovery)
4.FINALIZED
5.TEMP
前三個比較好記,都是以Replica開頭,而且只有DataNode中的塊被稱為Replica(備份)
我們還需要介紹一下兩個比較重要的概念BGS,GS。有了這兩個概念才能展開講。
1.GS ( Generation Stamp ) : 這是被NameNode維護的一個類似版本標簽的全局唯一標識,他是一個8字節的整數,當一個NameNode格式化文件系統的時候,這個標識被初始化為1
以下的事件能夠讓GS+1
1.當客戶端請求NameNode創建一個新的文件
2.當客戶端請求NameNode打開一個文件來以便向里面追加(append)內容或者刪減內容(truncate)
3.當客戶端在流水線工作過程中失敗,需要恢復流水線,客戶端回向NameNode討要一個新的GS
4.NameNode以客戶端的名義續租(Lease Recovery) 詳見 : Hadoop架構: 關於Recovery (Lease Recovery , Block Recovery, PipeLine Recovery)
GS + 1后將被寫入到NameNode的日志記錄里。
2.BGS (Block Generation Stamp) :其實是沒有這個概念的,但是為了區分GS,提出來了。BGS用來標記一個Block(以及他的Replica)的版本。以區分Replica是否過期
【在NameNode中數據塊被稱作Block,在DataNode中數據塊是Block的備份,被稱為Replica】的版本。
一.BGS在文件創建或者append時的處理。
1新建. 當客戶端向NameNode申請創建文件或者打開文件進行追加的時候,往往都需要一個新的Block,NameNode會為這個Block打上一個新的BGS。新BGS產生方式很簡單,NameNode將現在的GS + 1就得到了新的BGS(NameNode同時要把 + 1后的GS寫到日志里)。一個塊的創建不僅要新的BGS,而且還需要新的BlockId來表示這個Block,並且NameNode需要給出Block的Replica能放在哪些DataNode上,也就是Block的Locations。(Locations不會被寫入日志,而是在NameNode啟動后接收DataNode的報告來獲取)。
2獲取. 客戶端將得到的新BGS和BlockId發布到流水線中,讓DataNode獲取,DataNode獲取到新的BlockId和BGS。如果客戶端的意圖是創建文件的話,會新建一個塊文件,如果是追加的話,會打開一個塊文件,最后的結果都是把新的BGS和BlockId寫入DataNode的MetaFile(存儲文件元數據的文件,元數據比如BGS,BlockId)。
3回復.如果第2步沒有錯誤,客戶端將通知NameNode,新建一個OpenFile事務,並且寫入日志。該事務包含當前正在寫入文件的完整路徑信息,以及每一個塊的BlockId和BGS。
二.在寫入時新建Block時
1.當在對一個塊進行寫入,如果客戶端要求NameNode創建一個新的Block,NameNode會創建新的Block並且新建StoreGS事務和OpenFile事務,並且寫入日志。前者記錄新產生的GS(每個Block被新建都要讓NameNode的GenerationStamp + 1),后者記錄文件所有Block的BGS和BlockId。
2.客戶端將從NameNode那里獲得的新Block的相關信息發布到流水線上,和一中的2差不多
簡單地理解,GS是整個文件系統的版本號,BGS是塊的版本號。
當某些退出DataNode集群很久的節點加入時,根據GS可以識別出他們是否是舊的節點。
BGS用來識別一個塊是否過期。只有未過期的塊才會被進行特定操作,下文會提及。
聰明的你可能已經發現,上述狀態中出現了一個難以理解的詞 “Recovery”
這個詞在客戶端記錄DataStreamer運作狀態的枚舉類BlockConstructionStage中也有出現
我們先聊一聊什么是 “Recovery”。詳見 Hadoop架構: 關於Recovery (Lease Recovery , Block Recovery, PipeLine Recovery)
如果你對Recovery有了大體理解,我們就可以來談談這些復雜的狀態之間是怎么轉換的了。
首先是在NameNode中
1.當客戶端Writer申請新建一個塊,NameNode就會在本地新建一個塊,這個block的狀態是UNDER_CONSTRUCTION
2.當NameNode為某個文件進行租約恢復(Lease Recovery),該文件的最后一個塊的狀態轉為UNDER_RECOVERY
3.當客戶端在寫文件的時候向NameNode申請一個新的Block(上一個Block寫滿了或者以不明原因endBlock),或者請求關閉文件,NameNode會把上一個Block的狀態設置為Commited,如果沒有最小備份數(可以在配置里自行設置)的DataNode向NameNode匯報自己收到了和NameNode中Block同BGS的Finalized態Replica,那么Commited狀態會保持下去。
4.當有最小備份數的DataNode向NameNode匯報,自己已經有關於這個塊的FINALIZED態Replica,並且BGS和NameNode的Block的BSG一樣。那么NameNode就會把自己的Block設置成COMPLETE態。
注:客戶端寫完一個塊,或者客戶端關閉某個文件,都會告知流水線上的DataNode,DataNode們收到了前述信息(關閉或者寫完),認為這個塊將被結束操作,會試圖把自己的Replica設置成FINALIZED態,並且向NameNode匯報。
其次是在DataNode中
1.當一個備份(塊的備份)被寫入數據的時候,被設置成RBW(Replica Being Writen),一個塊被創建,意味着要被寫入,所以處於RBW態。
當客戶端打開某個現有的文件打算追加(append)或者刪減(truncate),一般是最末尾的Replica被設置成RBW,因為一般是在文件末尾追加或者刪減。
RBW狀態的塊對Reader客戶端是可見的
2.RWR(Replica Waitting To Be Recovery),等待恢復的塊,當一個DataNode在流水線傳輸過程中宕機,那么當他重啟后,所有的之前在流水線中正在被寫的RBW態Replica都會轉換成RWR態
RWR態的Replica是不會再加入流水線了的,但是如果DataNode和寫客戶端Writer一同宕機,NameNode在租約恢復(Lease Recovery)時,會讓領袖DataNode對這些Replica進行操作。當租
約恢復,這些RWR狀態將成為FINALIZED。
3.RUR(Replica Under Recovery) 正在恢復的備份,租約恢復文件的當前備份中,可能有RBW(正在被寫入的備份)的,RWR(需要被恢復,DataNode宕機重啟導致RBW -> RWR)的,FINALIZED(流水線關閉階段會通知DataNode將Replica設置成FINALIZED)的,在租約恢復執行階段會被設置成RUR態。(在Hadoop架構: 關於Recovery (Lease Recovery , Block Recovery, PipeLine Recovery) 中有詳細講解)
4.FINALIZED,當客戶端Writer在一個Block寫滿后,將會通知流水線上的DataNode將對於Replica設置成FINALIZED態,爾后關閉流水線
5.TEMP 這個狀態是用來暫存Replica的,某個Block的最小備份數是3,原本有3台DataNode存有Replica,但是其中一台宕機了,那么NameNode需要把備份復制到新的一台DataNode A上,於是在A
那創建了一個TEMP狀態的Replica來將數據復制進去,如果復制成功那么又恢復到3個Replica了。如果A宕機,那么下次重啟的時候,這個TEMP的Replica將被刪除。