按照官方文檔的架構(gòu)一節(jié)昧辽,進行整理和擴充衙熔。同時借鑒網(wǎng)上的一些資料。先對HDFS有個整體上的認知搅荞,后面的具體細節(jié)再通過源碼去看。
聲明:本文是基于Apache Hadoop 2.9.1文檔進行總結(jié)的框咙。
架構(gòu)
寫文件流程
下面這個圖片總結(jié)性的描述了讀文件時客戶端與 HDFS 中的 namenode咕痛, datanode 之間的數(shù)據(jù)流動。
1.Client調(diào)用DistributedFileSystem對象的create方法喇嘱,創(chuàng)建一個文件輸出流(FSDataOutputStream)對象
2.通過DistributedFileSystem對象與Hadoop集群的NameNode進行一次RPC遠程調(diào)用茉贡,在HDFS的Namespace中創(chuàng)建一個文件條目(Entry),該條目沒有任何的Block
3.通過FSDataOutputStream對象者铜,向DataNode寫入數(shù)據(jù)腔丧,數(shù)據(jù)首先被寫入FSDataOutputStream對象內(nèi)部的Buffer中放椰,然后數(shù)據(jù)被分割成一個個Packet數(shù)據(jù)包
4.以Packet最小單位,基于Socket連接發(fā)送到按特定算法選擇的HDFS集群中一組DataNode(正常是3個愉粤,可能大于等于1)中的一個節(jié)點上砾医,在這組DataNode組成的Pipeline上依次傳輸Packet。
5.這組DataNode組成的Pipeline反方向上衣厘,發(fā)送ack如蚜,最終由Pipeline中第一個DataNode節(jié)點將Pipeline ack發(fā)送給Client
6.完成向文件寫入數(shù)據(jù),Client在文件輸出流(FSDataOutputStream)對象上調(diào)用close方法影暴,關(guān)閉流
7.調(diào)用DistributedFileSystem對象的complete方法错邦,通知NameNode文件寫入成功
讀文件流程
1.打開分布式文件:調(diào)用分布式文件 DistributedFileSystem.open( ) 方法;
2.尋址請求:從 NameNode 處得到 DataNode 的地址型宙,DistributedFileSystem使用 RPC 方式調(diào)用了NameNode撬呢,NameNode 返回存有該副本的DataNode 地址,DistributedFileSystem 返回了一個輸入流對象(FSDataInputStream)妆兑,該對象封裝了輸入流 DFSInputStream魂拦;
3.連接到DataNode:調(diào)用輸入流 FSDataInputStream.read( ) 方法從而讓DFSInputStream 連接到 DataNodes;
4.從 DataNode 中獲取數(shù)據(jù):通過循環(huán)調(diào)用 read( ) 方法箭跳,從而將數(shù)據(jù)從 DataNode 傳輸?shù)娇蛻舳耍?br>
5.讀取另外的 DataNode 直到完成:到達塊的末端時候晨另,輸入流 DFSInputStream 關(guān)閉與 DataNode 連接, 尋找下一個 DataNode谱姓;
6.完成讀取借尿,關(guān)閉連接:即調(diào)用輸入流 FSDataInputStream.close( );
副本放置策略
簡要概況起來3點:
- 1st replica. 如果寫請求方所在機器是其中一個datanode,則直接存放在本地,否則隨機在集群中選擇一個datanode.
- 2nd replica. 第二個副本存放于不同第一個副本的所在的機架.
- 3rd replica.第三個副本存放于第二個副本所在的機架,但是屬于不同的節(jié)點.
如果副本數(shù)大于3屉来,那么第四個以及后面的副本放置是隨機的路翻,但是要滿足下面兩個條件:
- 1個節(jié)點最多放置一個副本
- 一個機架不超過(replicas - 1) / racks + 2個副本
所以總的存放效果圖如下所示
這里橙色區(qū)域表示的就是writer寫請求者,綠色區(qū)域就是1個副本.從這里可以看出,HDFS在容錯性的設計上還是做了很多的思考的.從下文開始主要分析的就是BlockPlacementPolicyDefault默認放置策略,至于BlockPlacementPolicyWithNodeGroup也會稍微提一提,但是二者主要區(qū)別其實不大.
副本選擇策略
NameNode對文件的讀優(yōu)化的實現(xiàn)很簡單,基本原理就是按照客戶端與DataNode節(jié)點之間的距離進行排序茄靠,距客戶端越近的DataNode節(jié)點越被放在前面茂契,該算法的基本思路如下:
1.如果該Block的一個副本存在于客戶端,則客戶端優(yōu)先從本地讀取該數(shù)據(jù)塊慨绳;
2.如果該Block的一個副本與客戶端在同一個機架上掉冶,且沒有一個副本存放在客戶端,則客戶端優(yōu)先讀取這個同機架上的副本脐雪;否則客戶端優(yōu)先讀取同機器的副本厌小,失敗的情況下然后再優(yōu)先考慮這個同機架上的副本;
3.如果該Block既沒有一個副本存在客戶端战秋,又沒有一個副本與客戶端在同一個機架上璧亚,則隨機選擇一個DataNode節(jié)點作為優(yōu)先節(jié)點。
安全模式
安全模式是HDFS所處的一種特殊狀態(tài)脂信,在這種狀態(tài)下癣蟋,文件系統(tǒng)只接受讀數(shù)據(jù)請求透硝,而不接受刪除、修改等變更請求疯搅。在NameNode主節(jié)點啟動時濒生,HDFS首先進入安全模式,DataNode在啟動的時候會向namenode匯報可用的block等狀態(tài)秉撇,當整個系統(tǒng)達到安全標準時甜攀,HDFS自動離開安全模式。如果HDFS處于安全模式下琐馆,則文件block不能進行任何的副本復制操作规阀,因此達到最小的副本數(shù)量要求是基于datanode啟動時的狀態(tài)來判定的,啟動時不會再做任何復制(從而達到最小副本數(shù)量要求)瘦麸。
安全模式相關(guān)的配置
系統(tǒng)什么時候才離開安全模式谁撼,需要滿足哪些條件?當收到來自datanode的狀態(tài)報告后滋饲,namenode根據(jù)配置厉碟,確定 1)可用的block占總數(shù)的比例、2)可用的數(shù)據(jù)節(jié)點數(shù)量符合要求之后屠缭,離開安全模式箍鼓。如果有必要,也可以通過命令強制離開安全模式呵曹。與安全模式相關(guān)的主要配置在hdfs-site.xml文件中款咖,主要有下面幾個屬性
dfs.namenode.replication.min
: 最小的文件block副本數(shù)量,默認為1.
dfs.namenode.safemode.threshold-pct
: 副本數(shù)達到最小要求的block占系統(tǒng)總block數(shù)的百分比奄喂,當實際比例超過該配置后铐殃,才能離開安全模式(但是還需要其他條件也滿足)。默認為0.999f跨新,也就是說符合最小副本數(shù)要求的block占比超過99.9%時富腊,并且其他條件也滿足才能離開安全模式。如果為小于等于0域帐,則不會等待任何副本達到要求即可離開赘被。如果大于1,則永遠處于安全模式肖揣。
dfs.namenode.safemode.min.datanodes
: 離開安全模式的最小可用(alive)datanode數(shù)量要求帘腹,默認為0.也就是即使所有datanode都不可用,仍然可以離開安全模式许饿。
dfs.namenode.safemode.extension
: 當集群可用block比例,可用datanode都達到要求之后舵盈,如果在extension配置的時間段之后依然能滿足要求陋率,此時集群才離開安全模式球化。單位為毫秒,默認為1.也就是當滿足條件并且能夠維持1毫秒之后瓦糟,離開安全模式筒愚。 這個配置主要是對集群的穩(wěn)定程度做進一步的確認。避免達到要求后馬上又不符合安全標準菩浙。
總結(jié)一下巢掺,要離開安全模式,需要滿足以下條件:
1)達到副本數(shù)量要求的block比例滿足要求劲蜻;
2)可用的datanode節(jié)點數(shù)滿足配置的數(shù)量要求陆淀;
3) 1、2 兩個條件滿足后維持的時間達到配置的要求先嬉。
EditLog 和 FsImage的相關(guān)問題
fsimage:保存了最新的元數(shù)據(jù)checkpoint轧苫,包含了整個HDFS文件系統(tǒng)的所有目錄和文件的信息(fsimage是存儲在文件系統(tǒng)中的序列化文件)。對于文件來說包括了數(shù)據(jù)塊描述信息疫蔓、修改時間含懊、訪問時間等;對于目錄來說包括修改時間衅胀、訪問權(quán)限控制信息(目錄所屬用戶岔乔,所在組)等。
editlog:主要是在NameNode已經(jīng)啟動情況下對HDFS進行的各種更新操作進行記錄滚躯,HDFS客戶端執(zhí)行所有的寫操作都會被記錄到editlog中雏门。
簡單來想,NameNode維護了文件與數(shù)據(jù)塊的映射表以及數(shù)據(jù)塊與數(shù)據(jù)節(jié)點的映射表哀九,什么意思呢剿配?就是一個文件,它切分成了幾個數(shù)據(jù)塊阅束,以及這些數(shù)據(jù)塊分別存儲在哪些datanode上呼胚,namenode一清二楚。fsimage就是在某一時刻息裸,整個hdfs 的快照蝇更,就是這個時刻hdfs上所有的文件塊和目錄,分別的狀態(tài)呼盆,位于哪些個datanode年扩,各自的權(quán)限,各自的副本個數(shù)访圃。然后客戶端對hdfs所有的更新操作厨幻,比如說移動數(shù)據(jù),或者刪除數(shù)據(jù),都會記錄在editlog中况脆。
為了避免editlog不斷增大饭宾,secondary namenode會周期性合并fsimage和editlog成新的fsimage,新的操作記錄會寫入新的editlog中格了,這個周期可以自己設置(editlog到達一定大小或者定時)看铆。
dfs.namenode.checkpoint.period
dfs.namenode.checkpoint.txns
下面介紹合并fsimage和editlog的過程
第一步:將hdfs更新記錄寫入一個新的文件——edits.new。
第二步:將fsimage和editlog通過http協(xié)議發(fā)送至secondary namenode盛末。
第三步:將fsimage與editlog合并弹惦,生成一個新的文件——fsimage.ckpt。這步之所以要在secondary namenode中進行悄但,是因為比較耗時棠隐,如果在namenode中進行,或?qū)е抡麄€系統(tǒng)卡頓算墨。
第四步:將生成的fsimage.ckpt通過http協(xié)議發(fā)送至namenode宵荒。
第五步:重命名fsimage.ckpt為fsimage,edits.new為edits净嘀。
通信協(xié)議
客戶端建立與NameNode機器建立一個可配置TCP端口的連接报咳,客戶端通過ClientProtocol 與NameNode進行通信。DataNode通過DataNode Protocol與NameNode通信挖藏。RPC將這兩種協(xié)議抽象出來暑刃。特別注意的是,NameNode從不會發(fā)起任何RPC膜眠,它只是響應客戶端或DataNode發(fā)起的RPC請求岩臣。
魯棒性
- 數(shù)據(jù)磁盤失效、心跳機制以及重備份
- 集群再均衡
- 數(shù)據(jù)完整性
- 元數(shù)據(jù)磁盤失效
- 快照
空間回收
當trash configuration使用時宵膨,在FS Shell刪除的文件不會被立即的從HDFS中移除架谎。相反,HDFS把他移動到一個垃圾箱目錄下(每個用戶都有自己的垃圾箱目錄 /user/<username>/.Trash)辟躏。只要文件還在垃圾箱中就可以被恢復谷扣。