1. 程式人生 > >Hadoop 基礎知識---之HDFS篇

Hadoop 基礎知識---之HDFS篇

Hadoop基礎知識

HDFS基礎知識

HDFS簡介

起源      

源於Google釋出的GFS論文

HDFS是Hadoop DistributeFile System 的簡稱,是Hadoop的一個分散式檔案系統。

設計目標

大檔案儲存:支援TB-PB級的資料量

高容錯:執行在商業硬體上,而商業硬體並不可靠

高吞吐量:為大量資料訪問的應用提供高吞吐量支援

適應場景:

大檔案訪問

流式資料訪問

不適合的場景

儲存大量小檔案

隨機讀取,低延遲讀取

HDFS設計目標

硬體錯誤是常態

副本冗餘機制

流式資料訪問

批量讀而非隨機讀

關注吞吐量而非相應時間                    

流式資料特點是:像流水一樣,不是一次過來而是一點一點“流”過來。而你流式資料也是一點一點處理。如果全部收到資料以後在處理,那麼延遲會很大,而且在很多場合會消耗大量記憶體。

大規模資料集    

典型檔案大小GB-TB級別

關注橫向現行擴充套件

簡單一致性模型

一次寫,多次讀

支援追加,不允許修改

HDFS的基本概念

資料塊(block)

大檔案會被分割成多個block進行儲存,block大小預設為128MB。----小於一個塊大小的檔案不會佔據整個塊的空間                                                 

每一個block會在多個datanode上儲存多份副本,預設是3份。

NameNode

記錄檔案系統的元資料------單一主元資料伺服器,其中包括每個檔案,檔案位置以及這些檔案及其所在的DataNode內的所有資料塊的記憶體對映。

維護檔案系統樹及整棵樹內所有的檔案和目錄                  

DataNode

儲存和管理資料塊

將資訊上報給NameNode

HDFS的架構

採用Master/Slave主從架構 

NameNode

記錄檔案系統的元資料

伺服器位置資訊和副本數

DataNode                        

儲存和管理資料庫

將資訊上報給NameNode

Client

HDFS 對外介面

從NameNode獲取檔案資訊

連線DataNode讀寫檔案      

NameNode的作用       

Namenode始終在記憶體中儲存metadata(metadata裡面儲存的是元資料,比如整個檔案系統的結構),用於處理“讀請求”。但是我們把東西放在記憶體中,記憶體是易失的。

所以到有“寫請求”到來時,namenode會首先寫editlog到磁碟,成功返回後,才會修改記憶體,並且向客戶端返回。

Hadoop會維護一個fsimage檔案,也就是namenode中metadata的映象,但是fsimage不會隨時與namenode記憶體中的metadata保持一致,而是每隔一段時間通過合併editlog來更新內容。Secondary namenode就是用來更新fsimage的。

管理檔案系統的名稱空間     

檔案系統元資料資訊:所有目錄和檔案

記錄名稱空間的改動和本身屬性的改動

名稱空間映象檔案:fsimage

編輯日誌檔案:editLog

保持資料塊的節點資訊     

不持久化儲存,重啟系統是DataNode重建

協調客戶端(client)對檔案的訪問

fsimage和EditLog

fsimage     

最新的元資料檢查點
fsimage: filesysystem image的簡寫,檔案映象。

客戶端修改檔案時候,先寫到Editlog,成功後才更新記憶體中的metadata資訊。只有對檔案操作成功的時候,才會寫到editlog。

Fsimage是檔案meta資訊的持久化的檢查點。                         

當namenode失敗的時候,檔案metadata資訊可以通過:載入fsimage檔案到記憶體中,在editlog中應用響應的操作。

Fsimage檔案中包含檔案metadata資訊,不包含檔案塊位置的資訊。

Namenode把檔案塊位置資訊儲存在記憶體中,這些位置資訊是,在datanode加入叢集的時候,namenode詢問datanode得到的,並且不斷的更新。

EditLog

命令空間的變化

Fsimage,EditLog合併

SecondaryNamenode 週期性合併,生成新的fsimage,EditLog記錄新的變化。         

1. namespaceID :是檔案系統的唯一識別符號,在檔案系統首次格式化之後生成的

2. cTime :表示 NameNode 儲存時間的建立時間,由於筆者我的 NameNode 沒有更新過,所以這裡的記錄值為 0,以後對 NameNode 升級之後,cTime 將會記錄更新時間戳

3. storageType :說明這個檔案儲存的是什麼程序的資料結構資訊(如果是 DataNode,storageType=DATA_NODE)

4. blockpoolID:是針對每一個Namespace 所對應的 blockpool 的 ID,上面的這個 BP-391569129-10.6.3.43-1450226754562 就是在我的 nameserver1 的 namespace下的儲存塊池的 ID,這個 ID 包括了其對應的NameNode 節點的 ip 地址。

5. layoutVersion :表示 HDFS 永久性資料結構的版本資訊, 只要資料結構變更,版本號也要遞減,此時的 HDFS 也需要升級,否則磁碟仍舊是使用舊版本的資料結構,這會導致新版本的 NameNode 無法使用

6. clusterID :是系統生成或手動指定的叢集 ID

$dfs.namenode.name.dir/current/seen_txid這個檔案非常重要,是存放 transactionId 的檔案,format 之後是 0,它代表的是 namenode 裡面的 edits_*檔案的尾數,namenode 重啟的時候,會按照 seen_txid 的數字,循序從頭跑 edits_0000001~ 到 seen_txid 的數字。所以當你的 hdfs 發生異常重啟的時候,一定要比對seen_txid 內的數字是不是你 edits 最後的尾數,不然會發生建置 namenode 時 metaData 的資料有缺少,導致誤刪 Datanode 上多餘 Block 的資訊。

Secondary NameNode工作原理

Secondary NameNode作用

1.      對HDFS元資料的冷備份,預防NameNode出現故障丟失資料。

2.      解決EditLog增大的問題

其工作流程如下:

如上圖,Secondary NameNode主要是做Namespace image和Edit log合併的。

當客戶端執行寫操作,則NameNode會在Editlog記錄下來(有點像oracle的online redo log file),並在記憶體中儲存一份檔案系統的元資料。

Namespace image(fsimage)檔案是檔案系統元資料的持久化檢查點,不會再寫操作後馬上更新,因為fsimage寫非常慢(這個比較像datafile)。

由於EditLog不斷增長,在NameNode重啟時,會造成長時間NameNode處於安全模式,不可用狀態,是非常不符合Hadoop的設計初衷。所以要週期性合併Edit log,但是這個工作由NameNode來完成,會佔用大量資源,這就出現了Secondary NameNode,它可以進行image檢查點的處理工作。步驟如下:

(1)      Secondary NameNode請求NameNode進行Editlog的滾動(即建立一個新的Editlog),將新的編輯操作記錄到新生成的Edit log檔案。

(2)      通過http get方式,讀取NameNode上的fsimage和edit檔案,到Secondary NameNode上。

(3)      讀取fsimage到記憶體中,即載入fsimage到記憶體,然後執行edits中所有操作(類似Oracle Data Guard,應用redo log),並生成一個新的fsimage檔案,即這個檢查點被建立(fsimage.chpt)。

(4)      通過http post方式,將新的fsimage檔案傳送到NameNode。

(5)      NameNode使用新的fsimage替換原來的fsimage檔案,讓(1)建立的edits替代原來的edits檔案;並且更新fsimage檔案的檢查點時間。

整個處理過程完成。

SecondaryNameNode的處理,是將fsimage和edits檔案週期的合併,不會造成NameNode重啟時造成長時間不可訪問的情況。

DataNode的作用

DataNode是檔案系統的工作節點,它們根據客戶端或者是NameNode的排程儲存和檢索資料,並且定期向NameNode傳送它們所儲存的塊(block)的列表。

叢集中的每個伺服器都執行一個DataNode後臺程式,這個後臺程式負責把HDFS資料塊讀寫到本地的檔案系統。當需要通過客戶端讀/寫某個資料時,先有NameNode告訴客戶端去哪個DataNode進行具體的讀/寫操作,然後,客戶端直接與這個DataNode伺服器上的後臺程式進行通訊,並且對相關的資料塊進行讀/寫操作。

儲存並檢索資料塊

供客戶端或NameNode排程

定期向NameNode傳送儲存塊的列表

NameNode中儲存檔案和塊之間的所屬關係

DataNode中儲存資料塊和本地檔案的對應關係

HDFS讀寫操作圖

讀取資料流程

客戶端要訪問HDFS中的一個檔案

首先從namenode獲得組成這個檔案的資料塊位置列表

根據列表知道儲存資料塊的datanode

訪問datanode獲取資料

NameNode並不參與資料實際傳輸

寫入資料流程

客戶端請求namenode建立新檔案

客戶端將資料寫入DFSOutputStream

建立pipeline依次將目標資料塊寫入多個datanode,建立多個副本

HDFS的忌諱

低延遲場景  

將HDFS用於對資料訪問要求低延遲的場景:由於HDFS是為高資料吞吐量應用而設計的,必然以高延遲為代價。

儲存大量小檔案      

HDFS中元資料(檔案的基本資訊)儲存在namenode的記憶體中,而namenode為單點,小檔案資料大到一定程度,namenode記憶體就吃不消了。

HDFS架構優勢

降低namenode工作負載      

NameNode不處理資料

並行讀寫任務    

NameNode將任務分配給DataNode,可以並行處理讀寫任務。

充分利用頻寬。

資料塊block

HDFS中資料讀寫的最小單位

磁碟塊:512位元組

檔案系統塊:幾千位元組

HDFS塊:128MB(預設)

不足128MB的塊在實際磁碟中不會佔用128MB的空間。

塊大小的選擇

目標:最小化定址開銷,降到1%以下

塊太小:定址時間佔比高

塊太大,map數太少,作業變慢。

採用塊儲存的優勢

檔案的資料塊可分佈於不同磁碟

元資料和塊分開儲存,元資料統一管理

通過資料備份,提供資料容錯能力和可用性

多個副本,提高讀取效能,結合hadoop計算框架,計算跟著資料走  

資料塊和副本 

副本考量

數量

佈局

可靠性,寫入頻寬,讀取頻寬折中

預設副本數3

預設佈局
第1個放在客戶端所在節點

第2個同機架的不同節點

第3個放在不同機架的另外一個節點

很好的穩定性,負載均衡,較好的寫入頻寬,讀取效能,塊均勻分佈

HDFS網路拓撲

頻寬稀缺,距離標準

簡單衡量

網路看作樹,節點間距離是到共同祖先的距離總和

HDFS可靠性

冗餘副本策略    

機架策略

心跳機制

DataNode週期性向NameNode傳送心跳訊號和塊報告

NameNode根據報告驗證元資料

複製副本

DataNode失效造成某些塊副本數下降(複製對使用者透明)

其它原因:副本本身損壞,磁碟錯誤,複製因子增大

安全模式

在啟動Hadoop叢集的時候,叢集的執行會首先進入到安全模式(SafeMode)下。在此階段,DataNode會像NameNode上傳它們資料塊的列表,讓NameNode得到塊的位置資訊,並對每個檔案對應的資料塊副本進行統計。當最小副本條件滿足時,即一定比例的資料塊都達到最小副本數,系統就會退出安全模式,而這需要一定的延遲時間。當最小副本條件未達到要求時,就會對副本數不足的資料塊安排DataNode進行復制,直至達到最小副本數。而在安全模式下,系統會處於只讀狀態,NameNode不會處理任何塊的複製和刪除命令。

Namenode啟動時首先進入安全模式

只讀狀態,無法修改

直到datanode上報的block數達到閾值

上報的block個數/要求的個數,預設0.999

離開安全模式

自然離開:上報block數達到閾值

安全模式恢復

引起安全模式的原因

Block上報不足-----datanode沒啟動,磁碟壞了,伺服器壞了

NameNode磁碟滿------檢查log,會有相關exception

使用者強制關機等操作不當(特別注意!)----block損壞,checksum不一致。

故障查詢

找到datanode不能正常啟動的原因,重新啟動

清理namenode磁碟

謹慎操作,有問題找星環,注意資料丟失

校驗和

元資料保護

Hadoop使用者期望在儲存或處理資料時沒有丟失或者損壞。然而,每一個磁碟或者網路的讀寫IO操作都可能導致資料錯誤,當流經過系統的海量資料和HADOOP的處理極限一樣大的,資料損壞的機會是很高的。

通常的資料校驗方法是在資料第一次進入系統時計算資料的校驗和,當它在一個不可信的通道傳播時有可能導致資料孫河在此校驗。如果新生成的資料的校驗和與原始的不能精確匹配,那麼就認為它是損壞的。這個技術沒有提供修復資料的方法----它僅僅監測錯誤。它有可能是校驗和損壞而不是資料損壞,但是這個機率很小,因為校驗和比資料小的多。

    一個普遍使用的監測錯誤的是CRC-32(32-bitcyclic redundancy check),它對任意大小的輸入產生一個32位的校驗和。CRC-32用在Hadoop的checksumfilesystem 中用來做校驗和處理,同時HDFS使用一個更有效的變體叫CRC-32C。

HDFS中的資料完整性

HDFS校驗所有寫入/讀取的資料。每dfs.bytes-perchecksum的byte資料會產生一個單獨的校驗和。預設是512byte,因為CRC-32校驗和長度是4byte,儲存開銷小於1%。

Datanode在接觸資料儲存之前,負責檢查資料及校驗。這適用於他們從客戶端接收的資料和複製時從其它datanode接收的資料。客戶端把資料傳送到datanode組成的pipeline,pipeline中的最後一個datanode檢查校驗和。如果這個datanode檢測到錯誤,客戶端接收到一個IOException的子類,需要它處理(例如,重新執行操作)。

當客戶端從datanode讀取資料時,他們也會檢查校驗和,把它與儲存了這個資料的datanode比較。每一個datanode都儲存了校驗和驗證日誌,所以它知道它的每一個bolock的最後驗證時間。當客戶端驗證成功一個block,它告訴datanode,datanode會更新它的日誌。像這樣保持統計資訊在監測損壞磁碟時很有價值。

除了客戶端讀取時會檢驗block之外,每一個datanode執行一個datablockscanner,它會週期性監測datanode中所儲存的所有block。這樣做是為了房子物理儲存媒介的位衰落。

    由於HDFS儲存了block的副本,它可以通過拷貝好的副本來“恢復”損壞的block。它的工作方式是如果客戶端讀取block時發現一個錯誤,在丟擲一個checksumexception之前,它會試圖從namenode讀取的block和datanode報告給namenode,nodenode標記這個block為損壞的,這樣它不會把客戶端定位到它或把它拷貝到別的datanode。然後它從其它的datanode上拷貝一個副本,這樣複製銀子回覆到期望水平。一旦複製完畢,刪除損壞的副本。

HDFS2     

Hadoop2.X中的HDFS(version 2.0)相比於Hadoop1.X增加了兩個重要功能,HA和Federation。HA解決了Hadoop1.XNameNode中一直存在的單點故障問題,HA策略通過熱備的方式為主。NameNode提供一個備用者,並且這個備用者的狀態一直和主NameNode的元資料保持一致,一旦主NameNode掛了,備用NameNode可以立馬轉換為主NameNode,從而提供不間斷的服務。另外,Federation特性,主要是允許一個HDFS叢集中存在多個NameNode同時對我提供服務,這些NameNode分管一部分目錄(水平切分),彼此之間相互隔離,但共享底層的DataNode儲存資源。   

HDFS HA

解決NameNode單點故障

HDFS Federation

解決NameNode記憶體瓶頸,允許HDFS中多個NameNode

HDFS 快照

儲存HDFS某一時間的只讀映象

HDFS HA

單點問題

一個叢集中只有一個NameNode,宕機或者升級維護需要停止整個叢集

解決可用性問題:7*24服務

解決辦法

1.x 版本中,secondarynamenode 恢復時間慢,部分資料丟失

2.x 版本中,HA QJM,熱切換

HDFS2.0 HA的架構

1.      兩個NameNode,分別是active和standby,某一時刻只有一個active,可以切換,active修改記錄寫在共享儲存中的Editlog,standby監聽。

2.      DataNode同時向兩個NameNode傳送資料塊列表,做到熱切換。

3.      Active修改記錄寫在共享儲存中的editlog,standby監聽。

4.      Zookeeper FailoverController監控NameNode的執行情況,當active掛掉,快速切換,切斷原active的連線,防止腦裂fencing。

上面的圖裡,可以看出HA的大致架構,其設計上的考慮包括:

利用共享儲存來在兩個NN間同步edits資訊。

以前的HDFS是share nothing but NN,現在是NN又share storage,這樣其實是轉移了單點故障的位置,但中高階的儲存裝置內部都有各種RAID以及冗餘硬體包括電源以及網絡卡等,比伺服器的可靠性還是略有提高。通過NN內部每次元資料變動後的flush操作,加上NFS的close-to-open,資料的一致性得到了保證。社群現在試圖把元資料儲存放到Zookeeper上,以去除對共享儲存的依賴。

DataNode同時向兩個NN彙報塊資訊。

這是讓Standby NN保持叢集最新狀態的必須步驟。

用於監視和控制NN程序的FaioverController程序。不能在NN程序內進行性等資訊同步,最簡單的原因,一次Full GC就可以讓NN掛起十幾分鍾,所以,必須有一個獨立的短小精悍的watchdog來專門負責監控。這也是一個鬆耦合的設計,以便於擴充套件或者更改,目前版本里是Zookeeper來做同步鎖,但使用者可以方便的把這個Zookeeper FailoverController替換為其他的HA方案。

隔離(Fencing),防止腦裂,保證在任何時候只有一個主NN,包括三個方面:

共享儲存fencing,確保只有一個NN可以寫入edits。

客戶端fencing,確保只有一個NN可以享用客戶端的請求。

DataNode fencing,確保只有一個NN可以向Datanode下發命令,譬如刪除塊,複製塊,等。

HA方案(NFS)

失效隔離措施fencing

切斷原active的連線防止腦裂

共享儲存:只有一個namenode能寫

客戶端:只有一個namenode響應請求

DataNode:只有一個Namenode能下命令

NFS限制

HA能力受限於共享目錄

NFS本身的單點失效,冗餘硬碟,網路,電源

Hadoop Journal Node作用

NameNode之間共享資料(NFS,QuorumJournal Node(用的多))

兩個NameNode為了資料同步,會通過一組稱作JournalNodes的獨立程序進行相互通訊。當Active狀態的NameNode的命令空間有任何修改的時候,會告知大部分的Journal Nodes程序。Standby狀態的NameNode有能力讀取JournalNodes中的變更資訊,並且一直監控editlog的變化,把變化應用於自己的名稱空間。Standby可以確保叢集出錯時,名稱空間狀態已經完全同步了。

Hadoop 中的NameNode好比是人的心臟,非常重要,絕對不可以停止工作。在Hadoop 1時代,只有一個NameNode。如果NameNode資料丟失或者不能工作,那麼整個叢集就不能恢復了。這是Hadoop 1中的單點問題,也是Hadoop 1不可靠的表現。

Hadoop 2.2.0(HA)中HDFS的高可靠指的是可以同時啟動2個NameNode。其中一個處於工作狀態,另一個處於隨時待命狀態。這樣,當一個NameNode所在的伺服器宕機時,可以在資料不丟失的情況下,手工或者自動切換到另一個NameNode提供服務。這些NameNode之間通過共享資料,保證資料的狀態一致。多個NameNode之間共享資料,可以通過Network Filesystme或者Quorum Journal Node。前者是通過linux共享的檔案系統,屬於作業系統的配置;後者是Hadoop自身的東西,屬於軟體配置。

Quorum Journal Node方式:

叢集啟動時,可以同時啟動兩個NameNode。這些NameNode只有一個是Active的,另一個屬於standby狀態。Active狀態意味著提供服務,standby狀態意味著處於休眠狀態,只進行資料同步,時刻準備著提供服務。

在一個典型的HA叢集中,每個NameNode是一臺獨立的伺服器。在任一時刻,只有一個NameNode處於active狀態,另一個處於standby狀態。其中,active狀態的NameNode負責所有的客戶端操作,standby狀態的NameNode處於從屬地位,維護者資料狀態,隨時準備切換。

兩個NameNode為了資料同步,會通過一組稱作JournalNodes的獨立程序進行相互通訊。當active狀態的NameNode的命令空間有任何修改時,會告知大部分的JournalNodes程序。Standby狀態的namenode有能力讀取JournalNodes的變更資訊,並且一直監控editlog的變化,把變化應用於自己的名稱空間。Standby可以確保在叢集出錯時,名稱空間狀態已經完全同步了。

為了確保快速切換,standby狀態的NN有必要知道叢集中所有資料塊的位置。為了做到這一點,所有的DataNode必須配置兩個NN的地址,傳送資料塊位置資訊和心跳給他們兩個。

對於HA叢集而言,確保同一時刻只有一個NN處於active狀態是至關重要的。否則,兩個NN的資料狀態就會產生分歧,可能丟失資料。為了確保這一點,JounalNodes必須確保同一時刻只有一個NN可以向自己寫資料。

執行的JournalNodes程序非常輕量,可以部署在其它的伺服器上。注意:必須允許至少3個節點,當然可以執行更多,但是必須是奇數個。

QJM(Qurom Journal Manager)

背景

CDH4之前,在HDFS叢集中NN儲存單點故障(SPOF)。對於只有一個NN的叢集,如果NN叢集出現故障,那麼整個叢集將無法使用,知道NN重新啟動。

NN主要在以下兩個方面影響HDFS叢集:

(1)NN叢集發生意外,比如宕機,叢集將無法使用,知道管理員重啟NN。

(2)NN叢集需要升級,包括軟體,硬體升級,此時叢集也將無法使用。

HDFS的HA功能通過配置Active/Standby兩個NN實現在叢集中對NN的熱備來解決上述問題。如果出現故障,如機器崩潰或者機器需要升級,這是可通過此種方式將NN很快的切換到另外一臺機器。

架構                             

HDFS HA的解決方案可謂百花齊放,Linux HA, VMware FT,sharedNAS+NFS,BookKeeper,QJM/QuorumJournal Manager,BackupNode等等。目前普遍採用的是shared NAS+NFS,因為簡單易用,但是需提供一個HA的共享儲存裝置。而社群以及把基於         QJM/Quorum JournalManager的方案merge到trunk了。Cloudera提供的發行版中也包含了這個feature,這種方案也是社群在未來發行版中預設的HA方案。

在HA具體實現方法不同的情況下,HA框架的流程是一致的。不一致的就是如何儲存和管理日誌。在Active NN和Standby NN之間要用共享的儲存日誌的地方,Active NN把Editlog寫到這個共享的儲存日誌的地方,Standby NN去讀取日誌然後執行,這樣Active和Standby NN記憶體中的HDFS元資料保持著同步。一份發生主從切換Standby NN可以儘快接管Active NN的工作。(雖然要經歷一小段時間讓原來Standby追上原來的Active,但是時間很短。)

儲存日誌的地方,目前採用最多的就是用共享儲存NAS+NFS。缺點是:

(1)      這個儲存裝置要求時HA的,不能掛掉。

(2)      主從切換時需要fencing方法讓原來Active NN不在寫Editlog,否則的話會發生brain-split,因為如果不阻止原來Active停止向共享儲存寫Editlog,那麼就有兩個Active NN了,這樣就會破壞HDFS的元資料了。對於防止brain-split,在QJM出現之前,常見的方法就是在發生主從切換的時候,把共享儲存上存放的Editlog的資料夾對原來Acitve NN的寫許可權拿掉,那麼就可以保證同時至多隻有一個Active NN,防止了破壞HDFS元資料。

Cloudera為解決這個問題提出了QJM/QuromJournal Manager,這是一個基於Paxos演算法實現的HDFS HA方案。

利用2N+1臺JournalNode儲存Editlog

最多容忍N臺伺服器掛掉

基於Paxos演算法

Paxos演算法是一種基於訊息傳遞的一致性演算法。這個演算法被認為是類似演算法中最有效的。

Paxos演算法解決的問題是一個分散式系統如何就某個值(決議)達成一致。

一個典型場景是,在一個分散式資料庫系統中,如果各節點的初始狀態一致,每個節點都執行相同的操作序列,那麼他們最後能得到一個一致的狀態。為保證每個節點執行相同的命令序列,需要在每一條指令上執行一個“一致性演算法”以保證每個節點看到的指令一致。

QJM設計方案

通過讀寫多個儲存節點,達到高可用性,並引入資料一致性演算法,防止異常造成的資料不一致性。

QJM的基本原理是用2N+1臺JournalNode儲存Editlog,每次寫資料操作有大多數(>=N+1)返回成功時即認為該次寫成功,保證資料高可用性。這個演算法能容忍的是最多有N臺機器掛掉,如果多於N臺掛掉,這個演算法就失效。

QJM寫操作

寫操作由主節點來完成,當主節點呼叫flush操作,會呼叫RPC同時向2N+1個JournalNode伺服器寫日誌,只要有N+1個節點返回成功,寫操作就說成功。

主節點會標記返回失敗的JN節點,下次寫日誌將不再寫該節點,直到下次呼叫滾動日誌操作,如果此時該JN節點恢復正常,之後主節點會向其寫日誌。雖然該節點對事部分日誌,由於主節點寫入了多份,因此相應的日誌並沒有丟失。

為了保證寫入每個日誌檔案txid的連續性,主節點保證分配的txid是連續的,同時JN節點在接受寫日誌的時候,首先會檢查txid是否跟上次寫繼續,如果不聯絡向主節點報錯,連續則寫入日誌檔案。

QJM讀操作

1.      從每個JN節點拿出所有日誌,按txid從小到大排序

2.      消化日誌,從小到大消化。集合中一個不行換一個。

當從節點除非讀日誌的時候,會經歷如下幾個步驟:

1.      選擇日誌檔案,建立輸入流

從節點遍歷出所有還沒有消化的日誌檔案,同時過濾inprocess狀態的檔案。對於每個JN節點上的日誌檔案,均按照txid從小到大進行排序放入一個集合。每個JN節點在從節點端均對應這樣一個集合。再將每個JN節點間相同的日誌檔案進行歸類為一組(組內日誌會檢查fisrtTxid是否相等,及其lastTxid是否相等);每個組之間再按照txid從小到大進行排序,這樣方便從節點按照txid順序消化日誌;同時也會判斷每個組之間txid是否連續。

2.      消化日誌

準備好輸入流以後,開始消化日誌,從節點按照txid先後順序從每個日誌組裡面消化日誌。在每個日誌組裡面,首先會檢查起始txid是否正確,如果正確,從節點先消化第一個日誌檔案,如果消化第一個日誌檔案失敗則消化第二個日誌檔案,以此類推,如果日誌組內檔案遍歷完還沒有找到需要的日誌,則該日誌消化失敗,消化每個日誌的如果消化的上一個txid等於該日誌檔案的lastTxid,則該日誌檔案消化結束。

優勢

不需要額外的共享儲存,降低了發咋讀和維護成本。

不需要單獨配置fencing實現,QJM內建了fencing

不存在單點失效

系統魯棒性可配置,能容忍最多N臺機器宕機

不會因為一臺JN延遲影響效能,也不會因為JN數量增多而影響效能

HDFS儲存架構的侷限性

HDFS雙層架構

當前HDFS架構有兩層,如下:

NameSpace

管理目錄,檔案,資料塊

-----支援常見的檔案系統操作,如建立檔案,修改檔案,刪除檔案。

Block Management

----- 塊管理:塊的修改及副本複製存放,建立資料塊,刪除資料塊等。

----- 物理儲存:儲存實際的資料塊。

當前的HDFS實現架構如下:

1.      NN實現Namespace和Block的管理

DN提供了物理的儲存和訪問Block資料,DN註冊到NN的block管理層,為HDFS提供Storage層。

2.      DN註冊到NN,然後與NN進行通訊,但是實際上DN與NN的block管理層通訊,而不

會參與NameSpace管理。

3.      因此block管理層一部分在DN中,一部分在NN中。

Block Identification:每個檔案都是由一個或多個block組成,每個block有一個64位的數字ID,全域性唯一。當前的叢集中僅有一個Namespace和一個block pool來做storage。

侷限性

Namespace和block managemeng高耦合
Namenode擴充套件性 

-----namenode只能存放在單個namenode上,而namenode在記憶體中儲存了整個分散式檔案系統中的元資料資訊,這限制了叢集中資料塊,檔案和目錄的數目。

制約效能

-----檔案操作的效能制約與單個NN的吞吐量

隔離性

某個使用者提交的負載很大的job會減慢其它使用者的job。

Federation 原理

為什麼採用Federation

採用Federation的最主要原因是簡單,Federation能夠快速的解決了大部分單NameNode的問題。

Federation整個核心設計實現大概用了4個月。大部分改變是在DataNode,Config和Tools,而NameNode本身的改動非常少,這樣NameNode原先的魯棒性不會受到影響。這使得該方案與之前的HDFS版本相容。

Federation架構

為了水平擴充套件namenode,Federation使用了多個獨立的namenode/namespace。這些namenode之間是聯合的,也就是說,他們之間互相獨立且不需要互相協調,各自分工,管理自己的區域。分散式的datanode被用作通用的資料庫儲存儲存裝置。每個datanode要向叢集中所有的namenode註冊,且週期性地向所有Namenode傳送心跳和塊報告,並執行來自所有NameNode的命令。

一個block pool由屬於同一個Namespace的資料塊組成,每個datanode可能會儲存叢集中所有block pool的資料塊。

每個block pool內部自治,也就是說各自管理各自的block,不會與其他的block pool交流。一個namenode掛掉了,不會影響其他namenode。

某個namenode上的namespace和它對應的block pool 一起被稱為namespace volume。它(namespace volume)是管理的基本單位。當一個namenode/namespace被刪除後,其所有datanode上對應的block pool也會被刪除。當叢集升級時,每個namespace volume作為一個基本單元進行升級。

多個NameNode/Namespace

每個NameNode擁有一個儲存池block pool

----相互獨立不需要協調,各自管理部分目錄

都可以對外服務

一個Name service掛了不影響其他的

Datanode向所有namenode傳送心跳和塊報告,為所有儲存池服務

Federation命令空間管理

Federation中存在多個名稱空間,如何劃分和管理這些名稱空間非常關鍵。在Federation中採用“檔名hash”的方法,應為該方法的locality 非常差,比如:檢視某個目錄下面的檔案,如果採用檔名hash的方法存放檔案,則這些檔案可能被放到不同namespace中,HDFS需要訪問所有namespace,代價過大。為了方便管理多個名稱空間,HDFS Federation採用了經典的Client Side Mount Table。

如上圖所示,下面四個深色三角形代表一個獨立的名稱空間,上方淺色的三角形代表從客戶角度去訪問的子名稱空間。各個深色的名稱空間Mount到淺色的表中,客戶可以訪問不同的掛載點來訪問不同的名稱空間,這就如同在Linux系統中訪問不同掛載點一樣。這就是HDFS Federation中名稱空間管理的基本原理:將各個名稱空間掛載到全域性mount-table中,就可以做將資料到全域性共享;同樣的名稱空間掛載到個人的mount-table中,這就成為應用程式可見的名稱空間檢視。

主要優點

擴充套件性和隔離性

支援多個namenode水平擴充套件整個檔案系統的namespace。可按照應用程式的使用者和種類分離namespace volume,進而增強了隔離性。

通用儲存服務

Block Pool抽象層為HDFS的架構開啟了創新之門。分離blockstorage layer使得:

(1)      新的檔案系統(non-HDFS)可以在block storage上構建

(2)      新的應用程式(如Hbase)可以在直接使用block storage層

(3)      分離的block storage層為將來完全分散式namespace打下基礎

Erasure Code

Erasure Code可以認為是RAID的通式,任何RAID都可以轉換為特定的Erasure Code。。在傳統的RAID中,僅支援少量的磁碟分佈,當系統中存在多個分發點和多節點時,RAID將無法滿足需求。比如RAID5只支援一個盤失效,即使是RAID6也僅支援兩個盤失效,所以支援多個盤失效的演算法也就是erasure code是解決這一問題的辦法。

原始n份資料,增加m份,通過n+m中的任意n份,還原出原始資料。定義中包含了encode和decode兩個過程,將原始的n份資料變為n+m份是encode,之後這n+m份資料可存放在不同的device上,如果有任意小於m份的資料失效,仍然能通過剩下的資料還原出來。

使用場景

凡是需要通過冗餘來進行高可用的場景。但總體來說,主要運用於儲存和數字編碼領域。

1) 陣列

如果磁碟陣列需要使用高階特性,比如需要能夠容錯兩個磁碟失效(RAID6),那麼可以用n+2的模式;如果想容錯4個磁碟失效,則可使用n+4的模式。

2) 雲端儲存

erasure code是雲端儲存的核心技術,最初諸如hadoop, GFS,CEPH等都採用的是n-way replication來做冗餘,但是這樣會帶來極大的成本開銷,因此幾乎各大公司都在用erasure code替代n-way replication,之後我還會簡要介紹一下具體他們使用的模式。

3) P2P領域

erasure code 的理論起碼也有20年的歷史了,但真正實踐可能也就最近幾年的時間,在P2P領域,動態的分佈和智慧的容錯,特別是對短暫失效是非常關鍵的。以往的演算法或多或少都有點山寨的感覺,而藉助erasure code之後,將會使P2P的演算法更具有數學的嚴謹性。

4) 數字編碼

erasure code本身就是出自編碼理論,所以在這一塊具有先天的優勢。