本編隨筆是小編我的參照我的的筆記、官方文檔以及網上的資料等後對HDFS的概念以及運行原理進行系統性地概括,提及來真的慚愧呀,自學了很長一段時間也沒有對Hadoop知識點進行概括,有時候在實戰中或者與別人交流Hadoop相關技術時,不少概念也只是模模糊糊記得,並不是很熟練。哈哈哈,趁着最後一個暑假,把本身這兩年自學的大數據開發技術都系統性概括,省得之後本身忘記了,順便分享到本身的博客上,也給初學者等有須要的人蔘考。html
寫博客不易,若是文章有錯誤,請指出,以爲不錯的話,請給個贊哈,謝謝~前端
Hadoop分佈式文件系統(HDFS)被設計成適合運行在通用硬件(commodity hardware)上的分佈式文件系統。它和現有的分佈式文件系統有不少共同點。但同時,它和其餘的分佈式文件系統的區別也是很明顯的。HDFS是一個高度容錯性的系統,適合部署在廉價的機器上。HDFS能提供高吞吐量的數據訪問,很是適合大規模數據集上的應用。HDFS放寬了一部分POSIX約束,來實現流式讀取文件系統數據的目的。HDFS在最開始是做爲Apache Nutch搜索引擎項目的基礎架構而開發的。HDFS是Apache Hadoop Core項目的一部分。java
Hadoop 是Apache基金會下一個開源的分佈式計算平臺,它以分佈式文件系統HDFS和MapReduce算法爲核心,爲用戶提供了系統底層細節透明的分佈式基礎架構。用戶能夠在不瞭解分佈式底層細節的狀況下,充分利用分佈式集羣進行高速運算和存儲。node
Hadoop是一個可以讓用戶輕鬆架構和使用的分佈式計算平臺。它主要有如下幾個 優勢:缺點: 算法
HDFS以流式數據訪問模式來存儲超大文件,運行於商用硬件集羣上。apache
如下是對HDFS的設計簡單描述(詳細能夠參閱該文章):vim
HDFS採用master/slave架構。一個HDFS集羣是有一個Namenode和必定數目的Datanode組成。Namenode是一箇中心服務器,負責管理文件系統的namespace和客戶端對文件的訪問。Datanode在集羣中通常是一個節點一個,負責管理節點上它們附帶的存儲。在內部,一個文件其實分紅一個或多個block,這些block存儲在Datanode集合裏。Namenode執行文件系統的namespace操做,例如打開、關閉、重命名文件和目錄,同時決定block到具體Datanode節點的映射。Datanode在Namenode的指揮下進行block的建立、刪除和複製。Namenode和Datanode都是設計成能夠跑在普通的廉價的運行Linux的機器上。HDFS採用java語言開發,所以能夠部署在很大範圍的機器上。一個典型的部署場景是一臺機器跑一個單獨的Namenode節點,集羣中的其餘機器各跑一個Datanode實例。這個架構並不排除一臺機器上跑多個Datanode,不過這比較少見。集羣中單一Namenode的結構大大簡化了系統的架構。Namenode是全部HDFS元數據的仲裁者和管理者,這樣,用戶數據永遠不會流過Namenode。緩存
下圖是Hadoop的架構設計圖:安全
Hadoop的架構設計圖服務器
每一個磁盤都有默認的數據塊大小,這是磁盤進行數據讀/寫的最小單位。構建於單個磁盤之上的文件系統經過磁盤塊來管理該文件系統中的塊,該文件系統塊的大小能夠是磁盤塊的整數倍。文件系統塊通常爲幾千字節,而磁盤塊通常爲512字節。但這些對於須要讀/寫文件的文件系統用戶來講是透明的。
HDFS一樣也有塊(block)的概念,可是大得多,默認爲128MB。與單一磁盤上的文件系統類似,HDFS上的文件也被劃分爲塊大小的多個分塊,做爲獨立的存儲單元。但與面向單一磁盤的文件系統不一樣的是,HDFS中小於一個塊大小的文件不會佔據整個塊的空間,例如當一個1MB的文件存儲在一個128MB的塊中時,文件只使用1MB的磁盤空間,而不是128MB。
HDFS中的塊爲何這麼大?HDFS的塊比磁盤的塊大,其目的是爲了最小化尋址開銷。若是塊足夠大,從磁盤傳輸數據的時間會明顯大於定位這個塊開始位置所需的時間。由於,傳輸一個由多個塊組成的大文件的時間取決於磁盤傳輸速率。可是塊大小這個參數也不會設置得過大,MapReduce中map任務一般一次只處理一個塊中的數據,所以若是任務數太少(少於集羣中的節點數量),做業的運行速度就會比較慢。
對分佈式文件系統中的塊進行抽象會帶來不少好處。
HDFS將每一個塊複製到少數幾個物理上相互獨立的機器上(默認爲3個),能夠確保在塊、磁盤或機器發生故障後數據不會丟失。若是發現一個塊不可用,系統會從其餘地方讀取另外一個複本,而這個過程對用戶是透明的。一個因損壞或機器故障而丟失的塊能夠從其餘候選地點複製到另外一臺能夠正常運行的機器上,以保證複本的數量回到正常水平。一樣,有些應用程序可能選擇爲一些經常使用的文件塊設置更高的複本數量進而分散集羣中的讀取負載。
在HDFS中顯示塊信息:
# hdfs fsck / -files -blocks
能夠執行命令修改HDFS的數據塊大小以及複本數量:
# vim $HADOOP_HOME/etc/hadoop/hdfs-site.xml
運行中的NameNode有以下所示的目錄結構:
#Mon Sep 29 09:54:36 BST 2014 namespaceID=1342387246 clusterID=CID-01b5c398-959c-4ea8-aae6-1e0d9bd8b142 cTime=0 storageType=NAME_NODE blockpoolID=BP-526805057-127.0.0.1-1411980876842 layoutVersion=-57
編輯日誌(edits log) :文件系統客戶端執行寫操做時,這些事務首先被記錄到edits中。NameNode在內存中維護文件系統的元數據;當被修改時,相關元數據信息也同步更新。內存中的元數據可支持客戶端的讀請求。咱們可使用OEV查看edits文件:
選項解析:
-i,--inputFile <arg>:要處理的編輯文件 -o,--outputFile <arg>:輸出文件的名稱;若是指定的文件存在,它將被覆蓋 -p,--processor <arg>:選擇要應用於編輯文件的處理器類型 (XML|FileDistribution|Web|Delimited) oev中的e指定了鏡像文件
命令以下:
<?xml version="1.0" encoding="UTF-8"?> <EDITS> <EDITS_VERSION>-63</EDITS_VERSION> <RECORD> <!-- 開始日誌段--> <OPCODE>OP_START_LOG_SEGMENT</OPCODE> <DATA> <!-- 事務id--> <TXID>1</TXID> </DATA> </RECORD> <RECORD> <!-- 結束日誌段--> <OPCODE>OP_END_LOG_SEGMENT</OPCODE> <DATA> <TXID>2</TXID> </DATA> </RECORD> </EDITS>
命名空間鏡像文件(fsimage):文件系統元數據的持久檢查點,每一個fsimage文件包含文件系統中的全部目錄和文件inode的序列化信息(從Hadoop-2.4.0起,FSImage開始採用Google Protobuf編碼格式),每一個inodes表徵一個文件或目錄的元數據信息以及文件的副本數、修改和訪問時間等信息。數據塊存儲在DataNode中,但fsimage文件並不描述DataNode。咱們可使用OIV查看fsimage文件 :
選項解析:
-i,--inputFile <arg>:要處理的鏡像文件 -o,--outputFile <arg>:輸出文件的名稱;若是指定的文件存在,它將被覆蓋 -p,--processor <arg>:選擇要應用於鏡像文件的處理器類型 (XML|FileDistribution|Web|Delimited) oiv中的i指定了image文件
命令以下:
# hdfs oiv -p XML -i fsimage_0000000000000014026 -o fsimage.xml
<?xml version="1.0"?> <fsimage> <NameSection> <!-- 默認的開啓編號--> <genstampV1>1000</genstampV1> <!-- 最後一個塊的編號--> <genstampV2>2215</genstampV2> <genstampV1Limit>0</genstampV1Limit> <!-- 最後一個分配的塊的塊id--> <lastAllocatedBlockId>1073743027</lastAllocatedBlockId> <!-- 開始的事務id號--> <txid>14026</txid> </NameSection> <INodeSection> <!-- 最後一個文件(目錄)的inode號--> <lastInodeId>18763</lastInodeId> <!--當前文件系統中只有根目錄,如下爲根目錄的相關信息--> <inode> <id>16385</id> <type>DIRECTORY</type> <name></name> <mtime>1560256204322</mtime> <permission>root:root:rwxrwxrwx</permission> <nsquota>9223372036854775807</nsquota> <dsquota>-1</dsquota> </inode> <inode> <id>16417</id> <type>DIRECTORY</type> <name>myInfo</name> <mtime>1552974220469</mtime> <permission>root:root:rwxrwxrwx</permission> <nsquota>-1</nsquota> <dsquota>-1</dsquota> </inode> <inode> <id>16418</id> <type>FILE</type> <name>myInfo.txt</name> <replication>1</replication> <mtime>1552830434241</mtime> <atime>1552974031814</atime> <perferredBlockSize>134217728</perferredBlockSize> <permission>root:root:rwxrwxrwx</permission> <blocks> <block> <id>1073741855</id> <genstamp>1031</genstamp> <numBytes>147</numBytes> </block> </blocks> </inode> ......... // inode文件太多,省略 </INodeSection> <INodeReferenceSection></INodeReferenceSection> <SnapshotSection> <snapshotCounter>0</snapshotCounter> </SnapshotSection> <INodeDirectorySection> <directory> <parent>16385</parent> <inode>18543</inode> <inode>16474</inode> <inode>16419</inode> <inode>16417</inode> <inode>16427</inode> <inode>17544</inode> <inode>17561</inode> </directory> <directory> <parent>16417</parent> <inode>16420</inode> </directory> <directory> <parent>16419</parent> <inode>17399</inode> <inode>17258</inode> <inode>16418</inode> <inode>17294</inode> </directory> ...... // 省略其餘<directory>標籤 </INodeDirectorySection> <FileUnderConstructionSection> </FileUnderConstructionSection> <SecretManagerSection> <currentId>0</currentId> <tokenSequenceNumber>0</tokenSequenceNumber> </SecretManagerSection> <CacheManagerSection> <nextDirectiveId>1</nextDirectiveId> </CacheManagerSection> </fsimage>
seen_txid文件 :該文件對於NameNode很是重要,它是存放transactionId的文件,format以後是0,它表明的是NameNode裏面的edits_*文件的尾數,NameNode重啓的時候,會按照seen_txid的數字,循序從頭跑edits_000*01~到seen_txid的數字。當hdfs發生異常重啓的時候,必定要比對seen_txid內的數字是否是你edits最後的尾數,否則會發生建置NameNode時元數據信息缺失,致使誤刪DataNode上多餘block。
in_use.lock文件 :是一個鎖文件,NameNode使用該文件爲存儲目錄加鎖。能夠避免其餘NameNode實例同時使用(可能會破壞)同一個存儲目錄的狀況。
NameNode管理文件系統的命名空間。它維護着文件系統樹及整棵樹內全部的文件和目錄。這些信息以兩個文件形式永久保存在本地磁盤上:命名空間鏡像文件(fsimage)和編輯日誌文件(edits log)。它也記錄着每一個文件中各個塊所在的數據節點信息,但它並不永久保存塊的位置信息,由於這些信息會在系統啓動時根據DataNode節點信息重建,塊信息存儲在內存中。
能夠看得出來NameNode的正常運行是很是重要的,若是運行的NameNode服務的機器毀壞,文件系統上全部的文件將會丟失,由於咱們不知道如何根據DataNode的塊重建文件。所以,Hadoop爲此提供兩種實現NameNode容錯機制:
Hadoop SecondaryNameNode並非Hadoop的第二個namanode,它不提供NameNode服務,而僅僅是NameNode的一個工具,這個工具幫助NameNode管理元數據信息。多是因爲SecondaryNameNode這個名字給人帶來的混淆,Hadoop後面的版本(1.0.4)建議不要使用,而使用CheckPoint Node。但在這小節中,小編仍是使用SecondaryNamenode。
運行中的SecondaryNamenode(輔助NameNode)的目錄結構與主NameNode的目錄結構幾乎同樣,但有部分時間不相同,它爲主NameNode內存中的文件系統元數據建立檢查點(後面解釋)還沒有成功時二者不相同。運行中的SecondaryNamenode有以下所示的目錄結構:
當NameNode 啓動時,須要合併fsimage和edits文件,按照edits文件內容將fsimage進行事務處理,從而獲得HDFS的最新狀態。實際應用中,NameNode不多從新啓動。假如存在一個龐大的集羣,且關於HDFS的操做至關頻繁與複雜,那麼就會產生一個很是大的edits文件用於記錄操做,這就帶來了如下問題:
此時,Secondary NameNode就要發揮它的做用了:合併edits文件,防止edits文件持續增加。該輔助NameNode會爲主NameNode內存中的文件系統元數據建立檢查點(fsimage文件),建立檢查點前HDFS會自動進入安全模式(safe mode),當NameNode處在安全模式,管理員也可手動調用hdfs dfsadmin -saveNameSpace命令來建立檢查點。建立檢查點的步驟以下所示(如圖中也簡單地描述)。
建立檢查點的步驟圖
最終,主NameNode擁有最新的fsimage文件和一個更小的正在進行中的edits文件(edits文件可能非空,由於在建立檢查點過程當中主NameNode還可能收到一些編輯請求)。這個過程清晰解釋了輔助NameNode和主NameNode擁有相近內存需求的緣由(由於輔助NameNode也把fsimage文件載入內存)。所以,在大型集羣中,輔助NameNode須要運行在一臺專用機器上。
在hdfs-site.xml中能夠配置與檢查點觸發點有關的屬性:
<property> <name>dfs.namenode.checkpoint.period</name> <value>3600</value> <description>兩個按期檢查點之間的秒數 </description> </property> <property> <name>dfs.namenode.checkpoint.txns</name> <value>1000000</value> <description>secondarynamenode或檢查點節點將建立檢查點 每一個「dfs.namenode.checkpoint.txns」事務的名稱空間 判斷「dfs.namenode.checkpoint.period」是否已過時 </description> </property> <property> <name>dfs.namenode.checkpoint.check.period</name> <value>60</value> <description>SecondaryNameNode和CheckpointNode將輪詢NameNode 每隔'dfs.namenode.checkpoint.check.period'秒查詢一次 未存入檢查點事務 </description> </property>
默認狀況下,輔助NameNode每隔一個小時建立檢查點;此外,若是從上一個檢查點開始編輯日誌的大小已經達到100萬個事務時,即便不到一小時,也會建立檢查點,檢查頻率爲每分鐘一次。
這個過程namesecondary目錄發生了更新;secondaryNameNode的檢查點目錄的佈局與NameNode的是相同的,這種設計的好處是NameNode發生故障時,能夠從secondaryNameNode恢復數據;有兩種實現方法:一是將相關存儲目錄複製到新的NameNode中;二是使用-importCheckpoint選項啓動NameNode守護進程,從而將secondaryNameNode用做新的NameNode
與第一次開啓hdfs過程不一樣的是這次有30多秒的安全模式:
在安全模式中在等待塊報告,這也關係到DataNode的運行過程。
DataNode是文件系統的工做節點。它們根據須要存儲並檢索數據塊(受客戶端或NameNode調度),而且按期向NameNode發送它們所存儲的塊的列表。
和NameNode不一樣的是,DataNode的存儲目錄是初始階段自動建立的,不須要額外格式化。DataNode的關鍵文件和目錄以下所示:
分析:從上圖能夠看出,dataNode的文件結構主要由blk_前綴文件、BP-random integer-NameNode-IP address-creation time和VERSION構成。
注 :當目錄中數據塊的數量增長到必定規模時,DataNode會建立一個子目錄來存放新的數據塊及其元數據信息。若是當前目錄已經存儲了64個(經過dfs.datanode.numblocks屬性設置)數據塊時,就建立一個子目錄。終極目標是設計一棵高扇出的目錄樹,即便文件系統中的塊數量很是多,目錄樹的層數也很少。經過這種方式,DataNode能夠有效管理各個目錄中的文件,避免大多數操做系統遇到的管理難題,即不少(成千上萬個)文件放在同一個目錄之中。
#Mon Sep 29 09:54:36 BST 2014storageID=DS-c478e76c-fe1b-44c8-ba45-4e4d6d266547 clusterID=CID-01b5c398-959c-4ea8-aae6-1e0d9bd8b142 cTime=0
datanodeUuid=75ffabf0-813c-4798-9a91-e7b1a26ee6f1
storageType=DATA_NODE layoutVersion=-57
in_use.lock :
是一個鎖文件,NameNode使用該文件爲存儲目錄加鎖。能夠避免其餘NameNode實例同時使用(可能會破壞)同一個存儲目錄的狀況。
一般DataNode從磁盤中讀取塊,但對於訪問頻繁的文件,其對應的塊可能被顯式地緩存在DataNode內存中,以堆外塊緩存(off-heap block cache)的形式存在。默認狀況下,一個塊僅緩存在一個DataNode的內存中,固然能夠對每一個文件配置DataNode的數量。做業調度器(用於MapReduce、Spark和其餘框架的)經過在緩存塊的DataNode上運行任務,能夠利用塊緩存的優點提升讀操做的性能。
用戶或應用經過在緩存池(cache pool)中增長一個 cache directive來告訴NameNode須要緩存哪些文件及存多久。緩存池是一個用於管理緩存權限和資源使用的管理性分組。
本小節只簡單描述,有關HDFS的緩存管理請查閱官方文檔或者其餘等相關資料。
NameNode在內存中保存文件系統中每一個文件和每一個數據塊的引用關係,這意味着對於一個擁有大量文件的超大集羣來講,內存將成爲限制系統橫向擴展的瓶頸。在2.X發行版本系列中引入的聯邦HDFS容許系統經過添加NameNode實現擴展,其中每一個NameNode管理文件系統命名空間中的一部分。
在聯邦環境中,每一個NameNode維護一個命名空間卷(namespace volume),由命名空間的元數據和一個數據塊池(block pool)組成,數據塊池包含該命名空間下文件的全部數據塊。命名空間卷之間是相互獨立的,兩兩之間並不相互通訊,甚至其中一個NameNode的失效也不會影響由其餘NameNode維護的命名空間的可用性。
集羣中的DataNode還須要註冊到每一個NameNode,而且存儲着來自多個數據塊池中的數據塊。
聯邦HDFS的架構圖以下圖所示:
聯邦HDFS架構圖
聯邦HDFS更詳細的請查閱官方文檔。
經過聯合使用在多個文件系統中備份NameNode的元數據和經過備用NameNode建立監測點能防止數據丟失,可是依舊沒法實現文件系統的高可用性。NameNode依舊存在單點失效(SPOF)的問題。若是NameNode失效了,那麼全部的客戶端,包括MapReduce做業,均沒法讀、寫或列舉文件,由於NameNode是惟一存儲元數據與文件到數據塊映射的地方,對於一個大型並擁有大量文件和數據塊的集羣,NameNode的冷啓動須要30分鐘,甚至更長時間,系統恢復時間太長了,也會影響到平常維護。在這一狀況下,Hadoop系統沒法提供服務直到有新的NameNode上線。
在這樣的狀況下要向從一個失效的NameNode恢復,系統管理員得啓動一個擁有文件系統元數據副本得新的NameNode,並配置DataNode和客戶端以便使用這個新的NameNode。新的NameNode直到知足如下情形才能相應服務:
Hadoop2.X以上版本針對上述問題增長了對HDFS高可用性(HA)的支持。在這一實現中,配置了一對活動-備用(active-standby) NameNode。當活動NameNode失效,備用NameNode就會接管它的任務並開始服務於來自客戶端的請求,不會有任何明顯中斷。實現這一目標須要在架構上作以下修改。HDFS HA架構圖以下所示:
HDFS HA架構圖
有兩種高可用性共享存儲能夠作出選擇:NFS過濾器或羣體日誌管理器(QJM, quorum journal manager)。QJM是一個專用的HDFS實現,爲提供一個高可用的編輯日誌而設計,被推薦用於大多數HDFS部署中,同時,QJM的實現並沒使用Zookeeper,但在HDFS HA選取活動的NameNode時使用了Zookeeper技術。QJM以一組日誌節點(journalnode)的形式運行,通常是奇數點結點組成,每一個JournalNode對外有一個簡易的RPC接口,以供NameNode讀寫EditLog到JN本地磁盤。當寫EditLog時,NameNode會同時向全部JournalNode並行寫文件,只要有N/2+1結點寫成功則認爲這次寫操做成功,遵循Paxos協議。其內部實現框架以下:
QJM內部實現框架
從圖中可看出,主要是涉及EditLog的不一樣管理對象和輸出流對象,每種對象發揮着各自不一樣做用:
上面提到EditLog,NameNode會把EditLog同時寫到本地和JournalNode。寫本地由配置中參數dfs.namenode.name.dir控制,寫JN由參數dfs.namenode.shared.edits.dir控制,在寫EditLog時會由兩個不一樣的輸出流來控制日誌的寫過程,分別爲:EditLogFileOutputStream(本地輸出流)和QuorumOutputStream(JN輸出流)。寫EditLog也不是直接寫到磁盤中,爲保證高吞吐,NameNode會分別爲EditLogFileOutputStream和QuorumOutputStream定義兩個同等大小的Buffer,大小大概是512KB,一個寫Buffer(buffCurrent),一個同步Buffer(buffReady),這樣能夠一邊寫一邊同步,因此EditLog是一個異步寫過程,同時也是一個批量同步的過程,避免每寫一筆就同步一第二天志。
這個是怎麼實現邊寫邊同步的呢,這中間實際上是有一個緩衝區交換的過程,即bufferCurrent和buffReady在達到條件時會觸發交換,如bufferCurrent在達到閾值同時bufferReady的數據又同步完時,bufferReady數據會清空,同時會將bufferCurrent指針指向bufferReady以知足繼續寫,另外會將bufferReady指針指向bufferCurrent以提供繼續同步EditLog。上面過程用流程圖就是表示以下:
EditLog輸出流程圖
既然EditLog是異步寫的,怎麼保證緩存中的數據不丟呢,其實這裏雖然是異步,但實際全部日誌都須要經過logSync同步成功後纔會給client返回成功碼,假設某一時刻NameNode不可用了,其內存中的數據實際上是未同步成功的,因此client會認爲這部分數據未寫成功。還有EditLog怎麼在多個JN上保持一致的呢?
解決方案:
1. 隔離雙寫
在ANN每次同步EditLog到JN時,先要保證不會有兩個NN同時向JN同步日誌,也就是說同一時間QJM僅容許一個NameNode向編輯日誌中寫入數據。這個隔離是怎麼作的。這裏面涉及一個很重要的概念Epoch Numbers,不少分佈式系統都會用到。Epoch有以下幾個特性:
但QJM是怎麼保證上面的特性的呢,主要有如下幾點:
這樣就能保證主備NN發生切換時,就算同時向JN同步日誌,也能保證日誌不會寫亂,由於發生切換後,原ANN的EpochNumber確定是小於新ANN的EpochNumber,因此原ANN向JN的發起的全部同步請求都會拒絕,實現隔離功能,防止了腦裂。
2. 恢復in-process日誌
若是在寫過程當中寫失敗了,可能各個JN上的EditLog的長度都不同,須要在開始寫以前將不一致的部分恢復。恢復機制以下:
3. 日誌同步
日誌從ANN同步到JN的過程,具體以下:
經過上面一些步驟,日誌能保證成功同步到JN,同時保證JN日誌的一致性,進而備NN上同步日誌時也能保證數據是完整和一致的。
這個讀過程是面向備NN(SNN)的,SNN按期檢查JournalNode上EditLog的變化,而後將EditLog拉回本地。SNN上有一個線程StandbyCheckpointer,會按期將SNN上FSImage和EditLog合併,並將合併完的FSImage文件傳回主NN(ANN)上,就是所說的Checkpointing過程。下面咱們來看下Checkpointing是怎麼進行的。
在2.x版本中,已經將原來的由SecondaryNameNode主導的Checkpointing替換成由SNN主導的Checkpointing。下面是一個CheckPoint的流向圖:
Checkpointing流向圖
總的來講,就是在SNN上先檢查前置條件,前置條件包括兩個方面:距離上次Checkpointing的時間間隔和EditLog中事務條數限制。前置條件任何一個知足都會觸發Checkpointing,而後SNN會將最新的NameSpace數據即SNN內存中當前狀態的元數據保存到一個臨時的fsimage文件( fsimage.ckpt)而後比對從JN上拉到的最新EditLog的事務ID,將fsimage.ckpt_中沒有,EditLog中有的全部元數據修改記錄合併一塊兒並重命名成新的fsimage文件,同時生成一個md5文件。將最新的fsimage再經過HTTP請求傳回ANN。經過按期合併fsimage有什麼好處呢,主要有如下幾個方面:
在活動namenode(ANN)失效以後,備用namenode(SNN)可以快速(幾十秒的時間)實現任務接管,由於最新的狀態存儲在內存中:包括最新的編輯日誌條目和最新的數據塊映射信息。實際觀察到的失效時間略長一點(須要1分鐘左右),這是由於系統須要保守肯定活動namenode是否真的失效了。活動namenode失效且備用namenode也失效的狀況下,固然這類狀況發生的機率很是低很是低的,如今Hadoop 3.X發行版本已經支持運行更多備用namenode來提供更高的容錯性。
系統中有一個稱爲故障轉移控制器(failover controller)的新實體,管理着將活動namenode轉移爲備用namenode的轉換過程。有多種故障轉移控制器,但默認一種是使用了Zookeeper來確保有且僅有一個活動namenode。每個namenode運行着一個輕量級的故障轉移控制器,其工做就是監視宿主namenode是否失效(經過一個簡單的心跳機制實現)並在namenode失效時進行故障轉移,這就是HA的主備切換機制,主備選舉依賴於Zookeeper。下面是主備切換的狀態圖:
Failover流程圖
從圖中能夠看出,整個切換過程是由ZKFC(即故障轉移控制器,全稱Zookeeper Failover Controller)來控制的,具體又可分爲HealthMonitor、ZKFailoverController和ActiveStandbyElector三個組件。
在故障切換期間,Zookeeper主要是發揮什麼做用呢,有如下幾點:
在哪些場景會觸發自動切換呢,從HDFS-2185中概括瞭如下幾個場景:
管理員也能夠經過手動發起故障轉移,例如在進行平常維護時,這稱爲」平穩的故障轉移「(graceful failover),由於故障轉移控制器能夠組織兩個namenode有序地切換角色。命令參考以下所示。
// 將 active 狀態由 nn1 切換到 nn2 # hdfs haadmin -failover --forcefence --forceactive nn1 nn2 // 在啓用自動故障轉移的集羣上 --forcefence -- forceactive 參數不起做用 // 使用如下方法檢查名稱節點狀態(假設 nn1 爲 active,nn2 standby): # hdfs haadmin -getServiceState nn1 active # hdfs haadmin -getServiceState nn2 standby // 因而咱們人爲製造故障,在 nn1 上查看 NameNode 進程 # jps # kill -9 [進程ID] // 自動故障轉移將會激活 nn2 節點,狀態從 standby 轉換爲 active
但在非平穩故障轉移的狀況下,沒法確切直到失效NameNode是否已經中止運行。例如網速較慢或者網絡被分割的狀況下,可能激發故障轉移,但Active NameNode依然運行着而且依舊是Active NameNode。高可用實現作了更一步的優化,以確保先前Active NameNode不會執行危害系統並致使系統崩潰的操做,該方法稱爲」規避「。
規避機制包括:撤銷NameNode訪問共享存儲目錄的權限(一般使用供應商指定的NFS命令)、經過遠程管理命令屏蔽相應的網絡端口。最不行的話,能夠經過「一槍爆頭」(斷電關機)等製造人爲故障技術。
HDFS讀數據流程圖
HDFS讀數據過程這一設計的一個重點是:客戶端能夠直接鏈接到DataNode檢索數據,且NameNode告知客戶端每一個塊所在的最佳DataNode,因爲數據流分散在集羣中的全部DataNode,因此這種設計能使HDFS擴展到大量的併發客戶端。同時,NameNode只須要響應塊位置的請求(這些信息存儲在內存中,於是很是高效),無需響應數據請求,不然隨着客戶端數量的增加,NameNode會很快稱爲瓶頸。
這裏HdfsDataInputStream是FSDataInputStream的子類,這裏是經過子類建立父類對象。
HDFS寫數據流程圖
參考資料 :《Hadoop權威指南(第四版)》
http://hadoop.apache.org/docs/stable/index.html
https://blog.csdn.net/baiye_xing/article/details/76268495#commentBox
https://www.jianshu.com/p/53e40d3b0f7d
http://www.javashuo.com/article/p-rfvoucjp-bx.html