1. 概述
HDFS集群分為兩大角色:NameNode、DataNode(Secondary NameNode)
NameNode負責管理整個文件系統(tǒng)的元數(shù)據(jù),記錄存放在哪些datanode中,以及存放路徑
dataNode 負責管理用戶的文件數(shù)據(jù)塊
文件會按照固定大?。╞locksize)來切分成塊后分布式存儲在若干臺datanode上
每一個文件快可以有多個副本,并存放在不同的datanode上
datanode 會定期向namenode匯報自身所保存的文件block信息,而namenode則會負責保持文件的副本數(shù)量(當減少datanode的時候,namenode才知道當前副本狀態(tài),從而進行副本維持)
HDFS的內(nèi)部工作機制對客戶端保持透明,客戶端請求訪問HDFS都是通過向namenode申請來進行
2. 寫數(shù)據(jù)流程
比較簡單,看圖即懂
3. 讀數(shù)據(jù)流程
比較簡單,看圖即懂
4. nameNode、secondNameNode管理元數(shù)據(jù)機制
4.1 機制
每次更新元數(shù)據(jù),namenode都需要記錄下來這些更新信息,方便之后查詢更新過的元數(shù)據(jù)。
假如每次記錄在磁盤上,幾千萬上億條元數(shù)據(jù)寫入速度會非常慢,導(dǎo)致磁盤IO使用率過高,效率低;讀數(shù)據(jù)的時候再上億條數(shù)據(jù)里面搜索,查詢的效率也非常低。
因此需要將更新記錄放在內(nèi)存中(new一個元數(shù)據(jù)對象),如果僅僅使用內(nèi)存,億級的數(shù)據(jù)又會使nameNode死機或者意外斷電,那么內(nèi)存中的記錄全部丟失。
所以需要把內(nèi)存中的億級元數(shù)據(jù)定時寫入fsimage中。由于一條元數(shù)據(jù)平均大小為150Bytes,定時時間太長的話中途斷電就丟失了,定時時間太短又會導(dǎo)致磁盤IO占用過高的問題。
這樣,secondNameNode就引入了,用于fsimage鏡像同步管理。
1. 用戶更新元數(shù)據(jù)時,將更新記錄寫入namenode內(nèi)存
2. 在第1步的同時,在namenode中,只將內(nèi)存中更新的記錄追加到日志文件(edits文件)中,這樣,即便是斷電了,nameNode也能根據(jù)edits操作日志就能恢復(fù)元數(shù)據(jù)的記錄信息。
但是這樣又會引入一個問題,edits文件變得越來越大,每次重啟的時候加載edits日志又會嚴重耗時,影響nameNode啟動速度。
這樣我們就需要一個元數(shù)據(jù)對象(在內(nèi)存中)的一個鏡像文件fsimage,那么edits文件就不用記錄每條元數(shù)據(jù)的完整信息,只用記錄對單條元數(shù)據(jù)的操作記錄,且定時將edits和fsimage鏡像文件合并。這樣斷電重啟時,只需要將fsimage與edits中未同步的少量操作記錄計算合并后的元數(shù)據(jù)完整信息加載到內(nèi)存中。
但是定時合并edits和fsimage也是一個很耗費資源的操作,且合并的同時,查詢操作就無法保證效率和正確性,從而引入了secondNameNode,將耗費資源的操作放到另一臺節(jié)點中。
3. 為了在定時合并edits和fsimage鏡像時區(qū)分合并了和未合并的操作記錄,這里需要拆分edits文件,未合并過的新操作記錄用edits_inprogress來區(qū)分,默認1分鐘拆分一次。
合并在hadoop namenode中專業(yè)術(shù)語是checkpoint,由secondNameNode發(fā)起詢問namenode是否需要checkpoint,如果達到限值namenode回給secondNameNode可以checkpoint,secondNameNode才發(fā)起checkpoint請求。
其實,定時觸發(fā)合并edits_inprogress記錄和fsimage鏡像的說法并不嚴格,實際上checkpiont觸發(fā)條件有2個:a。secondNameNode定時觸發(fā)詢問namenode是否需要出發(fā)checkpoint(默認是1小時一次);b。edits的size達到默認值:64MB,namenode才同意觸發(fā)checkpoint。
當secondNameNode請求觸發(fā)checkpoint時,namenode需要將edits_inprogress_idx改名為edits_idx,且新建edits_inprogress_idx+1用來記錄新增的操作。這樣secondNameNode可以沒有顧慮的做edits_idx和fsimage的checkpoint
4. 第一次做checkpoint時:secondNameNode將namenode的edits_idx和fsimage下載過來;之后再做checkpoint:secondNameNode只需要下載edits_idx+1,因為上一次的fsimage.checkpoint就是當先namenode的fsimage
5. 將下載過來的edits_idx和fsImage(fsimage.checkpoint)加載到內(nèi)存中進行運算
6. 將運算的結(jié)果dump到文件(覆蓋)fsimage.checkpoint
7. secondNameNode將fsimage.checkpoint上傳到namenode中
8. namenode 將fsimage.checkpoint替換舊的fsimage
默認edits文件1分鐘拆分一次,checkpoint詢問30分鐘一次
如果沒有新的edits記錄,則不會做checkpoint
當達到億級數(shù)據(jù)時,一定要考慮內(nèi)存的大小,以阿里云目前服務(wù)器最大支持512G來看,每條元數(shù)據(jù)平均150bytes,能存儲36億條元數(shù)據(jù)。每個元數(shù)據(jù)是一個文件,那么可以自行估算企業(yè)的實際情況。另外,元數(shù)據(jù)所指向的上傳的文件肯定是越大越好,且不要頻繁改動,適合存儲大文件(小文件要合并存放,例如每個小時的文件合并成一天的文件來存放到HDFS)?
namenode如果死機,secondNameNode不具備能夠替代的功能,因為secondNameNode只是用于做checkpoint的,所以一旦namenode死機,hadoop集群就不能運作了。
4.2 集群功能優(yōu)化配置參數(shù)
4.2.1 dfs.namenode.name.dir
如果namenode的硬盤損壞,元數(shù)據(jù)是可以恢復(fù)絕大部分的(沒有做checkpoint的edits_inprogress數(shù)據(jù)不能恢復(fù)),我們可以做個實驗來驗證:
1. #hadoop fs -ls /testdir
2. 立即刪除namenode的工作目錄 #rm -rf /kluter/hdpTmpDir/dfs/name, 這是,hadoop fs -ls /是可以正常工作的, 因為元數(shù)據(jù)信息還在namenode進程中
3. kill namenode進程,重啟namenode失敗,因為啟動時報錯:namenode工作目錄不存在了
4. 將secondNameNode的工作目錄cp到namenode的工作目錄,重啟namenode成功,但是發(fā)現(xiàn)第1步創(chuàng)建的testdir沒有恢復(fù)成功
5. 為了解決第4步的問題,我們在開始搭建的時候就必須規(guī)劃好硬件資源,在namenode上,需要掛載至少2塊磁盤:即便一塊磁盤掛了,另一塊磁盤中還是有相同完整數(shù)據(jù)的。需要修改hdfs-site.xml配置:
<property>
????<name>dfs.namenode.name.dir</name>
????<value>/kluter/hdpTmpDir/dfs/name,/kluter/hdpTmpDir/dfs/nameBak</value>
</property>
4.2.2?dfs.datanode.data.dir
同理datanode可以通過hdfs-site.xml中的dfs.datanode.data.dir來配置多個工作目錄到相同主機的不同硬盤,但并不是block在相同主機不同磁盤的復(fù)制(因為復(fù)制是在不同主機namenode之間)。
這個配置有2個作用:
? ? 1. 可以應(yīng)對多個hadoop客戶端同時傳文件到HDFS的情況,不同的客戶端將文件放在不同的磁盤,使用不同磁盤的IO并發(fā)進行,以減輕一塊磁盤IO的壓力。
? ? 2. 可以達到不增加namenode的情況下進行HDFS空間擴容,節(jié)約主機成本,只有磁盤費用的增加
4.2.3?dfs.namenode.secondary.http-address
這個參數(shù)是設(shè)置secondaryNameNode的節(jié)點IP和端口,默認是和namenode在同一臺主機
<property>
????<name>dfs.namenode.secondary.http-address</name>
????<value>10.10.77.193:50090</value>
</property>
4.2.4?dfs.namenode.checkpoint.period
checkpoint超時時間,默認值3600s=1小時,做實驗可以改成幾分鐘試試效果
4.2.5?dfs.namenode.checkpoint.dir
secondaryNameNode的工作目錄,當snn和nn在同一臺時有效,如果不在同一臺主機,nn會根據(jù)這個參數(shù)建立一個空的namesecondary目錄
4.3 其他
4.3.1?VERSION 文件
路徑:/kluter/hdpTmpDir/dfs/name/current/, namenode、datanode路徑相同
# cat VERSION
#Fri Jun 22 14:10:26 CST 2018
namespaceID=126653939
clusterID=CID-530c66ce-ec4f-4bea-895f-6bdda27c48fa
cTime=1529647826935
storageType=NAME_NODE
blockpoolID=BP-590588951-10.10.77.194-1529647826935
layoutVersion=-63
1. namespaceID:文件系統(tǒng)的唯一標識符,在文件系統(tǒng)首次格式化之后生成的;有多個集群的情況下,不同集群擁有不同的
2. storageType:說明這個文件系統(tǒng)存儲的是什么進程的數(shù)據(jù)結(jié)構(gòu)信息
3. cTime表示nn存儲時間的創(chuàng)建時間,如果nn更新升級,cTime將會記錄更新時間戳
4. layoutVersion表示HDFS永久性數(shù)據(jù)結(jié)構(gòu)的版本信息,只要數(shù)據(jù)結(jié)構(gòu)變更版本號也改變,此時HDFS也需要升級,否則磁盤仍舊是舊的版本數(shù)據(jù)結(jié)構(gòu),會導(dǎo)致新版本的nn無法使用
5. clusterID是系統(tǒng)生成或手動指定的集群ID。當有多個集群時,需要格式化一個指定集群就需要填寫對應(yīng)的cluster_id
4.3.2 namenode的seen_txid文件
路徑:/kluter/hdpTmpDir/dfs/name/current,只有namenode才有
作用是重啟namenode時,值會增加,用于namenode對edits_inprogress_idx進行回滾,每次重啟namenode時,nn就知道除了fsimage之外還需要將哪些edits文件進行加載該值等于inprogress的index,加載完fsimage和edits_inprogress文件后滾動新的edits_inprogress_idxNew
5. DataNode工作機制
1.
????存儲管理用戶的文件塊數(shù)據(jù)(block datas)
2.?
????定期向namenode匯報自身所持有的block信息(用于集群中某些block異常時,namenode知道如何去恢復(fù)初始副本數(shù)量),默認值21600000ms = 6hour,建議改成1小時=3600000
<property>
????<name>dfs.blockreport.intervalMsec</name>
????<value>3600000</value>
</property>
3. dataNode掉線timeout參數(shù)
如果dataNode因為各種原因死掉造成無法與namenode通信,namenode不會立即把該dn節(jié)點判定為掉線,要經(jīng)過一段時限,HDFS默認timeout為10分鐘+30秒,超時公式:timeout=2*heartbeat.recheck.interval + 10*dfs.heartbeat.interval
heartbeat.recheck.interval默認為300000ms=5分鐘,heartbeat.interval默認為3s?
假如手動kill一個datanode,也許你會覺得10分鐘+30s后namenode才認定datanode掛掉是一個很長的時間(實驗:kill zookeeper2這臺datanode,在網(wǎng)頁上發(fā)現(xiàn)datanode2的狀態(tài)依然是active),但實際上有可能datanode只是需要重啟一下,這樣不用頻繁的在網(wǎng)絡(luò)內(nèi)部發(fā)送消息,也不需要namenode立即去別的節(jié)點上同步數(shù)據(jù)來保證數(shù)據(jù)的copy數(shù)量