摘要:助輔助做元數(shù)據(jù)的備份。元數(shù)據(jù)存儲在內(nèi)存和磁盤中,這是因為磁盤的讀寫效率較低,而保存到內(nèi)存又有斷電消失的隱患。但磁盤中的元數(shù)據(jù)并不是最新的,內(nèi)存中的元數(shù)據(jù)才是實時的。將中的和復(fù)制到自身節(jié)點上并加載進內(nèi)存,根據(jù)的記錄操作更改元數(shù)據(jù)信息。
HDFS(Hadoop Distributed File System )
前言:最近正式進入了大數(shù)據(jù)框架的學習階段,文章來自個人OneNote筆記全部手碼,記錄學習僅作自勉與交流,如有錯誤希望交流指正。
HDFS概念:HDFS是一種用于在普通硬件上運行的分布式文件系統(tǒng),提供高度容錯的服務(wù),并被設(shè)計為部署在低成本的硬件上
HDFS適合批量處理,而不是用戶交互使用。重點是高吞吐量的數(shù)據(jù)訪問,而不是低延遲的數(shù)據(jù)訪問。
運行在HDFS上的應(yīng)用程序具有較大的數(shù)據(jù)集。因此,HDFS被調(diào)優(yōu)以支持大文件。
HDFS設(shè)計思想:
分而治之 負載均衡
??HDFS使用的典型塊大小為128 MB(此處指Hadoop2.X,Hadoop3.X默認256M)。盡可能的將每個塊駐留在不同的DataNode上。將超級大的文件切分成每一個小文件(數(shù)據(jù)塊)進行存儲在不同的節(jié)點上。同時切分的數(shù)據(jù)塊太大了,容易造成集群中節(jié)點的存儲的負載不均衡。太小了會造成一個文件切分過多的塊會造成NameNode的壓力過大。
??除了最后一個塊之外,文件中的所有塊都是相同大小的,如一個500M的文件被默認被切分成4*128M的文件塊,第四塊的大小為500-3×128=116M,每個block塊都有一個唯一的塊ID。如果想更改默認塊大小可以更改dfs.blocksize屬性。
冗余數(shù)據(jù) 提高容錯
??為了解決數(shù)據(jù)丟失的問題,hadoop使用空間換取數(shù)據(jù)安全,在hdfs中每一個數(shù)據(jù)塊都會進行備份存儲。默認的情況下每一個數(shù)據(jù)塊存儲3份。副本之前地位相同沒有優(yōu)先級,提供服務(wù)時誰有空誰服務(wù)。
??應(yīng)用程序可以指定文件的副本數(shù)量。復(fù)制因子(副本的數(shù)量)可以在文件創(chuàng)建時指定,以后可以更改。由于NameNode不允許DataNodes擁有同一個block的多個副本,也就是說同一個節(jié)點的多個數(shù)據(jù)塊中肯定沒有相同的。因此創(chuàng)建的副本的最大數(shù)量是當時的DataNodes總數(shù)。
??如果復(fù)制因子大于3,則隨機確定第4次復(fù)制和后續(xù)復(fù)制的位置,同時將每個rack(機架策略,下面會寫到) 的副本數(shù)量保持在上限以下(replicas - 1) / racks + 2。如果副本數(shù)量不符合設(shè)置則會根據(jù)條件自動管理,關(guān)系如下:
數(shù)據(jù)副本 < 復(fù)制因子:如果某個數(shù)據(jù)節(jié)點宕機導(dǎo)致數(shù)據(jù)副本小于復(fù)制因子則會復(fù)制此數(shù)據(jù)到另一個數(shù)據(jù)節(jié)點
數(shù)據(jù)副本>復(fù)制因子:如果因為上面的情況復(fù)制了數(shù)據(jù)之后,之前宕機的節(jié)點突然恢復(fù)運行,此時副本數(shù)大于復(fù)制因子則會刪除一個數(shù)據(jù)節(jié)點中的副本。
復(fù)制因子>DataNodes:如果復(fù)制因子大于數(shù)據(jù)節(jié)點總數(shù)NameNodes,而上面也提到了NameNode不允許單節(jié)點擁有同一個block的多個副本,則NameNode對這個block進行記錄,當集群中添加了新的DataNode時再復(fù)制補足副本
下圖為副本數(shù)的設(shè)置,可以在hdfs-site.xml文件中設(shè)置,如果不是設(shè)置的話默認為3。后續(xù)也可以通過在集成開發(fā)環(huán)境中編寫hdfs-site.xml或使用命令的方式設(shè)置,命令>IDE配置的文件>集群配置文件
HDFS采用一主多從架構(gòu)(Hadoop3.X已經(jīng)支持多個NameNode)
主:NameNode
存儲塊到DataNodes的映射元數(shù)據(jù)用于管理文件系統(tǒng)命名空間。
執(zhí)行文件系統(tǒng)命名空間操作,比如打開、關(guān)閉和重命名文件和目錄。
處理調(diào)節(jié)來自Client的讀寫請求。
負責分配block的存儲節(jié)點。
負責負載均衡。
助:SecondaryNameNode
輔助NameNode做元數(shù)據(jù)的備份、CheckPoint 。
輔助并分擔NameNode的壓力,當NameNode宕機時不能主動頂替NameNode,但是可以輔助NameNode的恢復(fù)。
從:DataNode
存儲數(shù)據(jù),管理自身節(jié)點的數(shù)據(jù)存儲。
真實的處理讀寫請求。
按指定周期向NameNode發(fā)送心跳報告。
元數(shù)據(jù)的概念:NameNode中存儲著元數(shù)據(jù),元數(shù)據(jù)包括(以下D表示存儲于磁盤disk,M表示內(nèi)存memory):
抽象目錄樹(DM)
數(shù)據(jù)與block的映射關(guān)系(DM)
block存儲的數(shù)據(jù)節(jié)點位置(M)
??元數(shù)據(jù)就像是所有數(shù)據(jù)的目錄一樣,集群啟動時會將磁盤中的元數(shù)據(jù)讀取到內(nèi)存,并根據(jù)DataNodes傳遞的心跳報告記錄block存儲的位置。元數(shù)據(jù)存儲在內(nèi)存和磁盤中,這是因為磁盤的讀寫效率較低,而保存到內(nèi)存又有斷電消失的隱患。但磁盤中的元數(shù)據(jù)并不是最新的,內(nèi)存中的元數(shù)據(jù)才是實時的。
下圖為NameNode元數(shù)據(jù)目錄下的截圖(路徑是手動設(shè)置的,不是默認路徑)
其中
edits_XXXXXXXXX-XXXXX 歷史日志文件,記錄了客戶端對數(shù)據(jù)的操作日志
edits_inprogress_XXXXXXXX 正在編輯的日志文件,記錄了目前對數(shù)據(jù)的操作
fsimage_xxxxxxxxx 元數(shù)據(jù)的一個持久化的CheckPoint,包含 Hadoop 文件系統(tǒng)中的所有目錄和文件元數(shù)據(jù)信息,但不包含文件塊位置的信息。該文件是通過真實元數(shù)據(jù)序列化的結(jié)果,集群啟動時對這些文件進行反序列化
seen_txid:合并點記錄文件,用戶對數(shù)據(jù)進行操作時不直接修改元數(shù)據(jù)而是記錄當前操作到日志文件,等集群空閑時再合并到元數(shù)據(jù)中,而合并點記錄文件中記錄的就是即將要合并的操作(還沒合并),這個合并的操作由SecondaryNameNode或指定的CheckPointNode來完成。
可以通過hdfs oiv將元數(shù)據(jù)轉(zhuǎn)換為其他格式文件(如XML)來查看,oev參數(shù)轉(zhuǎn)換日志文件,其中參數(shù)p表示轉(zhuǎn)換,參數(shù) i 表示輸入,參數(shù) o 表示輸出
hdfs oiv -p XML -i fsimage_0000000000000000062 -o fs62.xml hdfs oev -p XML -i edits_0000000000000000046-0000000000000000061 -o edit46.xml
將轉(zhuǎn)換好的文件從Linux下取出到Windows并使用VS Code格式化查看:
可以看到每一步操作都有非常詳細的記錄,將時間戳轉(zhuǎn)換為具體時間即可查看操作時間
上面提到了元數(shù)據(jù)的合并且由SecondaryNameNode完成(以下簡稱SNN)
CheckPoint由于磁盤內(nèi)的元數(shù)據(jù)相對于內(nèi)存中的元數(shù)據(jù)不是實時的,那么如何判斷何時該進行元數(shù)據(jù)合并呢?
CheckPoint默認觸發(fā)的條件有兩條,任意滿足一條都會啟動CheckPoint
距離上次元數(shù)據(jù)合并時間超過1小時
當前產(chǎn)生的操作記錄超過100W條,此條件每分鐘檢查一次
默認CheckPointNode為SNN,那么首先請求開始CheckPoint,要求NameNode停止操作edit_inprogress并將后面的操作寫入到一個新文件中。
SNN將NameNode中的fsimage和edits復(fù)制到自身節(jié)點上并加載進內(nèi)存,根據(jù)edits的記錄操作更改元數(shù)據(jù)信息。(在這個過程中需要注意的是如果不是第一次進行CheckPoint,那么SNN拉取的是合并點記錄文件編號到最新編輯日志文件中的文件,而不是所有文件)
SNN將合并好的元數(shù)據(jù)信息命名為fsimage.checkpoint并發(fā)送給NameNode,自己也保存一份
NameNode接收文件并將其改名為fsimage替換舊的元數(shù)據(jù)文件
如果在集群沒有達到CheckPoint條件的時候被正常關(guān)閉了,那么內(nèi)存中的完整元數(shù)據(jù)將會被序列化到磁盤元數(shù)據(jù)文件中。
HDFS四大機制
心跳機制:
NameNode如何確認DataNode存活?
每個DataNode定期向NameNode發(fā)送一條心跳消息,心跳報告間隔默認為3S。網(wǎng)絡(luò)分區(qū)可能導(dǎo)致DataNodes的子集與NameNode失去連接,NameNode通過心跳機制來檢測此情況,如果一個NameNode連續(xù)10次接收不到dataNode的心跳信息,會主動的對該DataNode發(fā)送兩次檢查,檢查的時間默認為五分鐘,兩次檢查失敗該DataNode將被標記為 死亡 ,并且不會再向它們發(fā)送任何IO請求。此外,DataNode每小時還需要向NameNode重新報告自身所有數(shù)據(jù)信息保證有效性。
已注冊死亡的DataNode的任何數(shù)據(jù)都不再適用于HDFS。DataNodeDeath可能導(dǎo)致某些塊的復(fù)制因子低于其指定值。NameNode經(jīng)常跟蹤需要復(fù)制的塊,并在必要時啟動復(fù)制。由于許多原因,重新復(fù)制的必要性可能會出現(xiàn):DataNode可能變得不可用,副本可能被破壞,DataNode上的硬盤可能會失敗,或者文件的復(fù)制因子可能會增加。
標記DataNodes死亡的超時時間是謹慎的(默認情況下超過10分鐘),以避免由DataNodes的狀態(tài)抖動引起的復(fù)制風暴。用戶可以設(shè)置較短的間隔以將DataNodes標記為陳舊的,并通過配置性能敏感的工作負載來避免在讀取和/或?qū)懭霑r陳舊的節(jié)點。
安全模式
如集群啟動時就進入了安全模式,不允許任何寫操作,此時發(fā)生了什么?
啟動NameNode并將磁盤中的元數(shù)據(jù)文件加載到內(nèi)存建立元數(shù)據(jù),并監(jiān)聽DataNode的請求與心跳
啟動DataNode并向NameNode發(fā)送心跳報告以注冊DataNode的存活狀況及block存儲信息
啟動SecondaryNameNode
準備完畢后只要集群內(nèi)的副本達到“最小副本條件”——文件系統(tǒng)中的每個副本數(shù) > 最小副本級別(默認為1),NameNode會在30S后退出安全模式
此外,用戶也可以手動使用命令進入和離開安全模式
機架策略
HDFS塊放置將通過在不同的機架上放置一個塊副本來使用機架感知實現(xiàn)容錯。這提供了在集群內(nèi)發(fā)生網(wǎng)絡(luò)交換機故障或分區(qū)時的數(shù)據(jù)可用性。如默認機架數(shù)為2,復(fù)制因子為3.
第一個副本一般存儲在客戶端所在的節(jié)點上(如果客戶端是一個DataNode的話,不是就隨機一個節(jié)點)
第二個副本存儲在和第一個副本不同的機架上的任意節(jié)點
第三個副本存儲在和第一個副本相同機架不同節(jié)點
負載均衡
每個數(shù)據(jù)節(jié)點存儲的數(shù)據(jù)與其硬件實力的比例差距不大,沒有絕對的均衡。集群規(guī)模較小可以使用默認的負載均衡,規(guī)模較大需要手動調(diào)整均衡屬性。自動調(diào)整負載均衡的帶寬,這里設(shè)置的帶寬是指負載均衡傳輸?shù)乃俾?,且自動負載均衡會在集群空閑的時候才啟動:
dfs.datanode.balance.bandwidthPerSec 1048576 //1M
命令方式手動負載均衡:
start-balancer.sh -t 10% //參數(shù)代表了各個節(jié)點數(shù)據(jù)占用率差值不超過10%時視為負載均衡
寫操作:
Client通過Distributed FileSystem向NameNode發(fā)送上傳文件的請求和文件信息
NameNode接收請求并分析文件信息決定是否允許上傳(文件/目錄是否存在,客戶端是否有權(quán)限)
如果NameNode分析同意上傳請求那么根據(jù)節(jié)點距離情況返回復(fù)制因子數(shù)目的數(shù)據(jù)節(jié)點列表信息(前提客戶端是一個數(shù)據(jù)節(jié)點,如果不是則首個節(jié)點隨機返回一個)
客戶端接收NameNode的允許響應(yīng)并對文件進行邏輯切分
準備上傳并構(gòu)建PipeLine,根據(jù)NameNode返回的返回的信息找到第一個寫入的數(shù)據(jù)節(jié)點,客戶端通過FSDataOutputStream模塊請求dn1上傳數(shù)據(jù),dn1收到請求會繼續(xù)調(diào)用dn2,然后dn2調(diào)用dn3,將這個通信管道建立完成。dn3、dn2、dn1逐級應(yīng)答客戶端。
以packet為單位上傳block(先寫入緩存)到通信管道中的每個節(jié)點
用傳輸?shù)谝粋€塊的方式完成其他塊的傳輸
所有塊傳輸完成后Client向NameNode發(fā)送傳輸狀態(tài)信息(成功或失敗)同時關(guān)閉FsDataOutputStream,NameNode根據(jù)狀態(tài)信息更新元數(shù)據(jù)。
讀操作:
Client通過Distributed FileSystem向NameNode發(fā)送下載文件請求
NameNode查詢元數(shù)據(jù),找到并返回文件塊所在的DataNode地址,如果找不到直接拋出異常。
客戶端獲取到block的數(shù)據(jù)節(jié)點會就近選擇節(jié)點按順序開始下載block
每個block下載完成后會進行checksum驗證,如果在某個DataNode讀取數(shù)據(jù)時發(fā)生錯誤則會通知NameNode并重新從其他擁有該block副本的DataNode進行下載
所有block下載完成后關(guān)閉FsDataOutputStream并由分布式文件系統(tǒng)向NameNode報告下載情況
關(guān)于HDFS寫操作失敗的結(jié)果網(wǎng)上說法不一,等學習的深入一些自行驗證,這里先記錄我看到的兩種:
說法一:如果在這個過程中有節(jié)點傳輸失敗HDFS默認會進行一次重試,再次失敗則放棄失敗的節(jié)點,從通信管道中刪除該節(jié)點并報告給NameNode,如果傳輸?shù)墓?jié)點全部失敗則重新向NameNode發(fā)起請求并構(gòu)建新的PipeLine,也就是說最少需要一個節(jié)點傳輸完成。未達到復(fù)制因子數(shù)量則在集群空閑時復(fù)制副本。
說法二:復(fù)制管道中的某一個DataNode無法將數(shù)據(jù)寫入磁盤,管道立即關(guān)閉。已發(fā)送的但尚未收到確認的數(shù)據(jù)包會被回退到隊列中,以確保管道中錯誤節(jié)點的下游節(jié)點可以獲得數(shù)據(jù)包。在剩下的健康數(shù)據(jù)節(jié)點中,正在寫入的數(shù)據(jù)塊被分配新的ID。當發(fā)生故障的數(shù)據(jù)節(jié)點恢復(fù)后,冗余的數(shù)據(jù)塊貌似不屬于任何文件而自動丟棄,由剩余節(jié)點組成的新復(fù)制管道會重新開放,繼續(xù)寫操作直至文件關(guān)閉
NameNode故障處理如果運行的過程中NameNode發(fā)生意外宕機了,可以使用以下方法進行挽救
將SecondaryNameNode中保存的備份數(shù)據(jù)復(fù)制到NameNode中,需要先將NameNode中的數(shù)據(jù)刪除
使用-importCheckpoint啟動NameNode守護進程,由hadoop修復(fù)NameNode
那么開始動手摧殘集群(這里先對虛擬機拍了快照)
如圖,啟動集群后殺死NameNode進程并刪除元數(shù)據(jù)文件夾,再次啟動NameNode,此時請求獲取根目錄文件列表失敗
[root@master hadoop]# jps //查看當前集群進程 8192 DataNode 8610 Jps 8451 NodeManager 8041 NameNode [root@master hadoop]# kill 8041 //殺死NameNode進程 [root@master hadoop]# rm -rf data/tmp/dfs/name/* //刪除元數(shù)據(jù)文件夾 [root@master hadoop]# sbin/hadoop-daemon.sh start namenode //多帶帶啟動NameNode starting namenode, logging to /usr/local/Software/hadoop/logs/hadoop-root-namenode-master.out [root@master hadoop]# bin/hadoop fs -ls / //請求文件列表失敗 19/08/04 15:38:25 WARN ipc.Client: Failed to connect to server: master/192.168.35.101:9000: try once and fail. java.net.ConnectException: 拒絕連接
那么現(xiàn)在嘗試恢復(fù)NameNode,將SecondaryNameNode的元數(shù)據(jù)備份復(fù)制到NameNode下,再次嘗試獲取集群中的數(shù)據(jù),成功獲取,至于第二種復(fù)制方法設(shè)置有點麻煩,下次有時間再補充記錄。
文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請注明本文地址:http://systransis.cn/yun/75772.html
閱讀 1298·2021-09-22 15:18
閱讀 2631·2021-09-22 15:17
閱讀 2246·2019-08-30 15:55
閱讀 1594·2019-08-30 15:54
閱讀 1074·2019-08-30 13:12
閱讀 642·2019-08-30 13:12
閱讀 1695·2019-08-29 11:33
閱讀 1458·2019-08-26 17:04