目錄
- 互斥機(jī)制
- 寫(xiě)流程
- 讀流程
- 恢復(fù)流程
在Hadoop2.X之前,Namenode是HDFS集群中可能發(fā)生單點(diǎn)故障的節(jié)點(diǎn),每個(gè)HDFS集群只有一個(gè)namenode,一旦這個(gè)節(jié)點(diǎn)不可用,則整個(gè)HDFS集群將處于不可用狀態(tài)。
HDFS高可用(HA)方案就是為了解決上述問(wèn)題而產(chǎn)生的,在HA HDFS集群中會(huì)同時(shí)運(yùn)行兩個(gè)Namenode,一個(gè)作為活動(dòng)的Namenode(Active),一個(gè)作為備份的Namenode(Standby)。備份的Namenode的命名空間與活動(dòng)的Namenode是實(shí)時(shí)同步的,所以當(dāng)活動(dòng)的Namenode發(fā)生故障而停止服務(wù)時(shí),備份Namenode可以立即切換為活動(dòng)狀態(tài),而不影響HDFS集群服務(wù)。
在一個(gè)HA集群中,會(huì)配置兩個(gè)獨(dú)立的Namenode。在任意時(shí)刻,只有一個(gè)節(jié)點(diǎn)作為活動(dòng)的節(jié)點(diǎn),另一個(gè)節(jié)點(diǎn)則處于備份狀態(tài)?;顒?dòng)的Namenode負(fù)責(zé)執(zhí)行所有修改命名空間以及刪除備份數(shù)據(jù)塊的操作,而備份的Namenode則執(zhí)行同步操作,以保持與活動(dòng)節(jié)點(diǎn)命名空間的一致性。
為了使備份節(jié)點(diǎn)與活動(dòng)節(jié)點(diǎn)的狀態(tài)能夠同步一致,兩個(gè)節(jié)點(diǎn)都需要同一組獨(dú)立運(yùn)行的節(jié)點(diǎn)(JournalNodes,JNS)通信。當(dāng)Active Namenode執(zhí)行了修改命名空間的操作時(shí),它會(huì)定期將執(zhí)行的操作記錄在editlog中,并寫(xiě)入JNS的多數(shù)節(jié)點(diǎn)中。而Standby Namenode會(huì)一直監(jiān)聽(tīng)JNS上editlog的變化,如果發(fā)現(xiàn)editlog有改動(dòng),Standby Namenode就會(huì)讀取editlog并與當(dāng)前的命名空間合并。當(dāng)發(fā)生了錯(cuò)誤切換時(shí),Standby節(jié)點(diǎn)會(huì)保證已經(jīng)從JNS上讀取了所有editlog并與命名空間合并,然后才會(huì)從Standby狀態(tài)切換為Active狀態(tài)。通過(guò)這種機(jī)制,保證了Active Namenode與Standby Namenode之間命名空間狀態(tài)的一致性,也就是第一關(guān)系鏈的一致性。
為了使錯(cuò)誤切換能夠很快的執(zhí)行完畢,就要保證Standby節(jié)點(diǎn)也保存了實(shí)時(shí)的數(shù)據(jù)快的存儲(chǔ)信息,也就是第二關(guān)系鏈。這樣發(fā)生錯(cuò)誤切換時(shí),Standby節(jié)點(diǎn)就不需要等待所有的數(shù)據(jù)節(jié)點(diǎn)進(jìn)行全量數(shù)據(jù)塊匯報(bào),而直接可以切換到Active狀態(tài)。為了實(shí)現(xiàn)這個(gè)機(jī)制,Datanode會(huì)同時(shí)向這兩個(gè)Namenode發(fā)送心跳以及塊匯報(bào)信息。這樣就實(shí)現(xiàn)了Active Namenode 和standby Namenode 的元數(shù)據(jù)就完全一致,一旦發(fā)生故障,就可以馬上切換,也就是熱備。
這里需要注意的是 Standby Namenode只會(huì)更新數(shù)據(jù)塊的存儲(chǔ)信息,并不會(huì)向namenode 發(fā)送復(fù)制或者刪除數(shù)據(jù)塊的指令,這些指令只能由Active namenode發(fā)送。
在HA架構(gòu)中有一個(gè)非常重非要的問(wèn)題,就是需要保證同一時(shí)刻只有一個(gè)處于Active狀態(tài)的Namenode,否則機(jī)會(huì)出現(xiàn)兩個(gè)Namenode同時(shí)修改命名空間的問(wèn),也就是腦裂(Split-brain)。腦裂的HDFS集群很可能造成數(shù)據(jù)塊的丟失,以及向Datanode下發(fā)錯(cuò)誤的指令等異常情況。為了預(yù)防腦裂的情況,HDFS提供了三個(gè)級(jí)別的隔離機(jī)制(fencing):
- 1.共享存儲(chǔ)隔離:同一時(shí)間只允許一個(gè)Namenode向JournalNodes寫(xiě)入editlog數(shù)據(jù)。
- 2.客戶端隔離:同一時(shí)間只允許一個(gè)Namenode響應(yīng)客戶端的請(qǐng)求。
- 3.Datanode隔離:同一時(shí)間只允許一個(gè)Namenode向Datanode下發(fā)名字節(jié)點(diǎn)指令,李如刪除、復(fù)制數(shù)據(jù)塊指令等等。
在HA實(shí)現(xiàn)中還有一個(gè)非常重要的部分就是Active Namenode和Standby Namenode之間如何共享editlog日志文件。Active Namenode會(huì)將日志文件寫(xiě)到共享存儲(chǔ)上。Standby Namenode會(huì)實(shí)時(shí)的從共享存儲(chǔ)讀取edetlog文件,然后合并到Standby Namenode的命名空間中。這樣一旦Active Namenode發(fā)生錯(cuò)誤,Standby Namenode可以立即切換到Active狀態(tài)。在Hadoop2.6中,提供了QJM(Quorum Journal Manager)方案來(lái)解決HA共享存儲(chǔ)問(wèn)題。
所有的HA實(shí)現(xiàn)方案都依賴于一個(gè)保存editlog的共享存儲(chǔ),這個(gè)存儲(chǔ)必須是高可用的,并且能夠被集群中所有的Namenode同時(shí)訪問(wèn)。Quorum Journa是一個(gè)基于paxos算法的HA設(shè)計(jì)方案。

Quorum Journal方案中有兩個(gè)重要的組件。
- 1.JournalNoe(JN):運(yùn)行在N臺(tái)獨(dú)立的物理機(jī)器上,它將editlog文件保存在JournalNode的本地磁盤(pán)上,同時(shí)JournalNode還對(duì)外提供RPC接口QJournalProtocol以執(zhí)行遠(yuǎn)程讀寫(xiě)editlog文件的功能。
- 2.QuorumJournalManager(QJM):運(yùn)行在NmaeNode上,(目前HA集群只有兩個(gè)Namenode),通過(guò)調(diào)用RPC接口QJournalProtocol中的方法向JournalNode發(fā)送寫(xiě)入、排斥、同步editlog。
Quorum Journal方案依賴于這樣一個(gè)概念:HDFS集群中有2N+1個(gè)JN存儲(chǔ)editlog文件,這些editlog 文件是保存在JN的本地磁盤(pán)上的。每個(gè)JN對(duì)QJM暴露QJM接口QJournalProtocol,允許Namenode讀寫(xiě)editlog文件。當(dāng)Namenode向共享存儲(chǔ)寫(xiě)入editlog文件時(shí),它會(huì)通過(guò)QJM向集群中所有的JN發(fā)送寫(xiě)editlog文件請(qǐng)求,當(dāng)有一半以上的JN返回寫(xiě)操作成功時(shí),即認(rèn)為寫(xiě)成功。這個(gè)原理是基于Paxos算法的。
使用Quorum Journal實(shí)現(xiàn)的HA方案有一下優(yōu)點(diǎn):
- 1.JN進(jìn)程可以運(yùn)行在普通的PC上,而無(wú)需配置專業(yè)的共享存儲(chǔ)硬件。
- 2.不需要單獨(dú)實(shí)現(xiàn)fencing機(jī)制,Quorum Journal模式中內(nèi)置了fencing功能。
- 3. Quorum Journa不存在單點(diǎn)故障,集群中有2N+1個(gè)Journal,可以允許有N個(gè)Journal Node死亡。
- 4. JN不會(huì)因?yàn)槠渲幸粋€(gè)機(jī)器的延遲而影響整體的延遲,而且也不會(huì)因?yàn)镴N數(shù)量的增多而影響性能(因?yàn)镹amenode向JournalNode發(fā)送日志是并行的)
互斥機(jī)制
當(dāng)HA集群中發(fā)生Namenode異常切換時(shí),需要在共享存儲(chǔ)上fencing上一個(gè)活動(dòng)的節(jié)點(diǎn)以保證該節(jié)點(diǎn)不能再向共享存儲(chǔ)寫(xiě)入editlog。基于Quorum Journal模式的HA提供了epoch number來(lái)解決互斥問(wèn)題,這個(gè)概念可以在分布式文件系統(tǒng)中找到。epoch number具有以下幾個(gè)性質(zhì)。
1.當(dāng)一個(gè)Namenode變?yōu)榛顒?dòng)狀態(tài)時(shí),會(huì)分配給他一個(gè)epoch number。
2.每個(gè)epoch number都是唯一的,沒(méi)有任意兩個(gè)Namenode有相同的epoch number。
3.epoch number 定義了Namenode寫(xiě)editlog文件的順序。對(duì)于任意兩個(gè)namenode ,擁有更大epoch number的Namenode被認(rèn)為是活動(dòng)節(jié)點(diǎn)。
當(dāng)一個(gè)Namenode切換為活動(dòng)狀態(tài)時(shí),它的QJM會(huì)向所有的JN發(fā)送命令,以獲取該JN的最后一個(gè)promise epoch變量值。當(dāng)QJM接受到了集群中多于一半的JN回復(fù)后,它會(huì)將所接收到的最大值加一,并保存到myepoch 中,之后QJM會(huì)將該值發(fā)送給所有的JN并提出更新請(qǐng)求。每個(gè)JN會(huì)將該值與自身的epoch值相互比較,如果新的myepoch比較大,則JN更新,并返回更新成功;如果小,則返回更新失敗。如果QJM接收到超過(guò)一半的JN返回成功,則設(shè)置它的epoch number為myepoch;,否則它終止嘗試為一個(gè)活動(dòng)的Namenode,并拋出異常。
當(dāng)活動(dòng)的NameNode成功獲取并更新了epoch number后,調(diào)用任何修改editlog的RPC請(qǐng)求都必須攜帶epoch number。當(dāng)RPC請(qǐng)求到達(dá)JN后,JN會(huì)將請(qǐng)求者的epoch與自身保存的epoch相互對(duì)比,若請(qǐng)求者的epoch更大,JN就會(huì)更新自己的epoch,并執(zhí)行相應(yīng)的操作,如果請(qǐng)求者的epoch小,就會(huì)拒絕相應(yīng)的請(qǐng)求。當(dāng)集群中大多數(shù)的JN拒絕了請(qǐng)求時(shí),這次操作就失敗了。
當(dāng)HDFS集群發(fā)生Namenode錯(cuò)誤切換后,原來(lái)的standby Namenode將集群的epoch number加一后更新。這樣原來(lái)的Active namenode的epoch number肯定小于這個(gè)值,當(dāng)這個(gè)節(jié)點(diǎn)執(zhí)行寫(xiě)editlog操作時(shí),由于JN節(jié)點(diǎn)不接收epoch number小于自身的promise epoch的寫(xiě)請(qǐng)求,所以這次寫(xiě)請(qǐng)求會(huì)失敗,也就達(dá)到了fencing的目的。
寫(xiě)流程
- 1.將editlog輸出流中緩存的數(shù)據(jù)寫(xiě)入JN,對(duì)于集群中的每一個(gè)JN都存在一個(gè)獨(dú)立的線程調(diào)用RPC 接口中的方法向JN寫(xiě)入數(shù)據(jù)。
- 2.當(dāng)JN收到請(qǐng)求之后,JN會(huì)執(zhí)行以下操作:
1)驗(yàn)證epoch number是否正確
2)確認(rèn)寫(xiě)入數(shù)據(jù)對(duì)應(yīng)的txid是否連續(xù)
3)將數(shù)據(jù)持久化到JN的本地磁盤(pán)
4)向QJM發(fā)送正確的響應(yīng)
- 3.QJM等待集群JN的響應(yīng),如果多數(shù)JN返回成功,則寫(xiě)操作成功;否則寫(xiě)操作失敗,QJM會(huì)拋出異常。
Namenode會(huì)調(diào)用FSEditlogLog下面的方法初始化editlog文件的輸出流,然后使用輸出流對(duì)象向editlog文件寫(xiě)入數(shù)據(jù)。
獲取了QuorumOutputStream輸出流對(duì)象之后,Namenode會(huì)調(diào)用write方法向editlog文件中寫(xiě)入數(shù)據(jù),QuorumOutputStream的底層也調(diào)用了EditsDoubleBuffer雙緩存區(qū)。數(shù)據(jù)回先寫(xiě)入其中一個(gè)緩沖區(qū)中,然后調(diào)用flush方法時(shí),將緩沖區(qū)中的數(shù)據(jù)發(fā)送給JN。
讀流程
Standby Namenode會(huì)從JN讀取editlog,然后與Sdtandby Namenode的命名空間合并,以保持和Active Namenode命名空間的同步。當(dāng)Sdtandby Namenode從JN讀取editlog時(shí),它會(huì)首先發(fā)送RPC請(qǐng)求到集群中所有的JN上。JN接收到這個(gè)請(qǐng)求后會(huì)將JN本地存儲(chǔ)上保存的所有FINALIZED狀態(tài)的editlog段落文件信息返回,之后QJM會(huì)為所有JN返回的editlog段落文件構(gòu)造輸入流對(duì)象,并將這些輸入流對(duì)象合并到一個(gè)新的輸入流對(duì)象中,這樣Standby namenode就可以從任一個(gè)JN讀取每個(gè)editlog段落了。如果其中一個(gè)JN失敗了輸入流對(duì)象會(huì)自動(dòng)切換到另一個(gè)保存了該edirlog段落的JN上。

恢復(fù)流程
當(dāng)Namenode發(fā)生主從切換時(shí),原來(lái)的Standby namenode會(huì)接管共享存儲(chǔ)并執(zhí)行寫(xiě)editlog的操作。在切換之前,對(duì)于共享存儲(chǔ)會(huì)執(zhí)行以下操作:
1.fencing原來(lái)的Active Namenode。這部分在互斥部分已經(jīng)講述。
2.恢復(fù)正在處理的editlog。由于Namenode發(fā)生了主從切換,集群中JN上正在執(zhí)行寫(xiě)入操作的editlog數(shù)據(jù)可能不一致。例如,可能出現(xiàn)某些JN上的editlog正在寫(xiě)入,但是當(dāng)前Active Namenode發(fā)生錯(cuò)誤,這時(shí)該JN上的editlog文件就與已完成寫(xiě)入的JN不一致。在這種情況下,需要對(duì)JN上所有狀態(tài)不一致的editlog文件執(zhí)行恢復(fù)操作,將他們的數(shù)據(jù)同步一致,并且將editlog文件轉(zhuǎn)化為FINALIZED狀態(tài)。
3.當(dāng)不一致的editlog文件完成恢復(fù)之后,這時(shí)原來(lái)的Standby Namenode就可以切換為Active Namenode并執(zhí)行寫(xiě)editlog的操作。
4.寫(xiě)editlog。在前面已經(jīng)介紹了。
日志恢復(fù)操作可以分為以下幾個(gè)階段:
1.確定需要執(zhí)行恢復(fù)操作的editlog段落:在執(zhí)行恢復(fù)操作之前,QJM會(huì)執(zhí)行newEpoch()調(diào)用以產(chǎn)生新的epoch number,JN接收到這個(gè)請(qǐng)求后除了執(zhí)行更新epoch number外,還會(huì)將該JN上保存的最新的editlog段落的txid返回。當(dāng)集群中的大多數(shù)JN都發(fā)回了這個(gè)響應(yīng)后,QJM就可以確定出集群中最新的一個(gè)正在處理editlog段落的txid,然后QJM就會(huì)對(duì)這個(gè)txid對(duì)應(yīng)的editlog段落執(zhí)行恢復(fù)操作了。
2.準(zhǔn)備恢復(fù):QJM向集群中的所有JN發(fā)送RPC請(qǐng)求,查詢執(zhí)行恢復(fù)操作的editlog段落文件在所有JN上的狀態(tài),這里的狀態(tài)包括editlog文件是in-propress還是FINALIZED狀態(tài),以及editlog文件的長(zhǎng)度。
3.接受恢復(fù):QJM接收到JN發(fā)回的JN發(fā)回的響應(yīng)后,會(huì)根據(jù)恢復(fù)算法選擇執(zhí)行恢復(fù)操作的源節(jié)點(diǎn)。然后QJM會(huì)發(fā)送RPC請(qǐng)求給每一個(gè)JN,這個(gè)請(qǐng)求會(huì)包含兩部分信息:源editlog段落文件信息,以及供JN下載這個(gè)源editlog段落的url。
接收到這個(gè)RPC請(qǐng)求之后,JN會(huì)執(zhí)行以下操作:
1)同步editlog段落文件,如果JN磁盤(pán)上的editlog段落文件與請(qǐng)求中的段落文件狀態(tài)不同,則JN會(huì)從當(dāng)前請(qǐng)求中的url上下載段落文件,并替換磁盤(pán)上的editlog段落文件。
2)持久化恢復(fù)元數(shù)據(jù),JN會(huì)將執(zhí)行恢復(fù)操作的editlog段落文件的狀態(tài)、觸發(fā)恢復(fù)操作的QJM的epoch number等信息(恢復(fù)的元數(shù)據(jù)信息)持久化到磁盤(pán)上。
3)當(dāng)這些操作都執(zhí)行成功后,JN會(huì)返回成功響應(yīng)給QJM,如果集群中的大多數(shù)JN都返回了成功,則此次恢復(fù)操作執(zhí)行成功。
4.完成editlog段落文件:到這步操作時(shí),QJM 就能確定集群中大多數(shù)的JN保存的editlog文件的狀態(tài)已經(jīng)一致了,并且JN持久化了恢復(fù)信息。QJM就會(huì)向JN發(fā)送指令,將這個(gè)editlog段落文件的狀態(tài)轉(zhuǎn)化為FINALIZED狀態(tài),,并且JN會(huì)刪除持久化的恢復(fù)元數(shù)據(jù),因?yàn)榇疟P(pán)上保存的editlog文件信息已經(jīng)是正確的了,不需要保存恢復(fù)的元數(shù)據(jù)。
到此這篇關(guān)于詳細(xì)講解HDFS的高可用機(jī)制的文章就介紹到這了,更多相關(guān)HDFS的高可用機(jī)制內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
您可能感興趣的文章:- HDFS-Hadoop NameNode高可用機(jī)制
- JAVA讀取HDFS的文件數(shù)據(jù)出現(xiàn)亂碼的解決方案
- Hadoop 分布式存儲(chǔ)系統(tǒng) HDFS的實(shí)例詳解
- JAVA操作HDFS案例的簡(jiǎn)單實(shí)現(xiàn)
- hadoop的hdfs文件操作實(shí)現(xiàn)上傳文件到hdfs