1. HDFS NameNode
**作用是接受客戶端的讀寫服務(wù),在內(nèi)存中保存文件元數(shù)據(jù)信息**
NameNode在內(nèi)存中保存的metadata包括:
(1)文件所屬ownership和權(quán)限permission,文件名等
(2)文件包含哪些塊block
(3)每個(gè)塊保存在哪個(gè)DataNode上(在集群啟動(dòng)時(shí)由DataNode上報(bào))
metadata不僅在內(nèi)存中有,還會(huì)將上面前兩點(diǎn)保存在磁盤上,文件名為fsimage。為了可用性考慮在磁盤上備份元數(shù)據(jù),一般在nfs上,如果元數(shù)據(jù)完全丟失了,整個(gè)集群的數(shù)據(jù)等于報(bào)廢。
而block位置信息不會(huì)保存,若關(guān)機(jī)則丟失。NameNode在啟動(dòng)時(shí)將fsimage加載到內(nèi)存中。
磁盤中還會(huì)保存edits文件,用于記錄對(duì)metadata的操作,即記錄文件增刪操作。不是立即對(duì)fsimage操作,而是在特定時(shí)刻由secondry NameNode幫助合并fsimage和edits,生產(chǎn)新的fsimage。
大概100w文件會(huì)占用1GB內(nèi)存
2. Secondary NameNode
**不是NameNode的備份(但可以做備份),主要工作是幫助NameNode定期合并edits,減少NameNode的啟動(dòng)時(shí)間和CPU、io壓力**
Secondary NameNode可以視為NameNode的元數(shù)據(jù)冷備,建議Secondary NameNode放在不同于NameNode的機(jī)器上
合并時(shí)機(jī)根據(jù)兩個(gè)配置參數(shù)決定
設(shè)置的時(shí)間間隔fs.checkpoint.period,默認(rèn)3600s
設(shè)置的edits最大體積 fs.checkpoint.size,默認(rèn)64MB
3. DataNode
**存儲(chǔ)數(shù)據(jù),默認(rèn)副本3個(gè),Hadoop2.6.4版本之后默認(rèn)塊大小128MB**
集群啟動(dòng)時(shí)DataNode會(huì)向NameNode匯報(bào)block信息。
以塊列表的形式存儲(chǔ)塊位置信息。
每3s向NameNode發(fā)送心跳包,如果NameNode 10min沒有收到心跳包,則會(huì)認(rèn)為該DataNode lost了。NameNode會(huì)尋找其他相對(duì)空閑的DataNode拷貝缺失副本。
一個(gè)block里面只可能有一個(gè)文件,即使該文件不到128MB,在邏輯上依然占用一個(gè)塊,但是在磁盤上占用實(shí)際大小,不會(huì)填充到128MB。
HDFS中的塊設(shè)置的這么大是為了最小化尋址開銷,將磁盤傳輸數(shù)據(jù)的時(shí)間作為首要時(shí)延。
4. HDFS讀過程
客戶端請(qǐng)求NameNode獲取文件的獲取文件起始?jí)K的位置。對(duì)于每一個(gè)塊,namenode返回存儲(chǔ)該塊的所有datanode地址,并按距離客戶端遠(yuǎn)近排序。通過對(duì)數(shù)據(jù)流反復(fù)調(diào)用read方法,可以將數(shù)據(jù)傳輸?shù)娇蛻舳恕5竭_(dá)塊的末端時(shí),尋找下一個(gè)最合適的DataNode傳輸。
客戶端還會(huì)驗(yàn)證從DataNode傳送過來的數(shù)據(jù)校驗(yàn)和。如果發(fā)現(xiàn)一個(gè)損壞的塊,那么客戶端將會(huì)再嘗試從別的DataNode讀取數(shù)據(jù)塊,向NameNode報(bào)告這個(gè)信息,NameNode也會(huì)更新保存的文件信息。
由客戶端并發(fā)讀取DataNode,這種設(shè)計(jì)的好處是,可以使HDFS擴(kuò)展到更大規(guī)模的客戶端并行處理,這是因?yàn)閿?shù)據(jù)的流動(dòng)是在所有DataNode之間分散進(jìn)行的。同時(shí)NameNode的壓力也變小了,使得NameNode只用提供請(qǐng)求塊所在的位置信息就行。

5. HDFS寫過程
客戶端請(qǐng)求NameNode新建文件,namenode在命名空間中確保該文件不存在并且該用戶有在路徑下寫文件的權(quán)限。namenode會(huì)切分文件并挑選一系列最適合存儲(chǔ)的DataNode,這一組DataNode構(gòu)成一個(gè)管線。客戶端將數(shù)據(jù)包傳給第一個(gè)DataNode,第一個(gè)DataNode傳給帶二個(gè)DataNode,以此類推。然后反向傳輸確認(rèn)回執(zhí),直到管線中所有DataNode都確認(rèn)成功寫入,才會(huì)回復(fù)成功代碼。
客戶端僅僅只寫一個(gè)副本,DataNode自行復(fù)制其他副本。這樣的優(yōu)點(diǎn)是快。

6. HDFS安全模式
NameNode啟動(dòng)的時(shí)候,會(huì)進(jìn)入安全模式,此時(shí)hdfs對(duì)外部客戶端是只讀的。
安全模式期間,NameNode將磁盤上的edits和fsimage加載到內(nèi)存,執(zhí)行edits上的各種操作,完成后將生成最新的fsimage文件和一個(gè)空edits。
同時(shí),NameNode會(huì)收集DataNode的塊信息匯報(bào),一個(gè)block達(dá)到了最小副本數(shù)以上時(shí),會(huì)被認(rèn)為是安全的。當(dāng)一定比例的數(shù)據(jù)塊(可設(shè)置)是安全的,結(jié)束安全模式。當(dāng)檢測到某些塊不足最小副本數(shù),會(huì)自行復(fù)制。
7. HDFS HA(High Avaliable)
Hadoop2.0比1.0的改進(jìn):
(1)解決NameNode單點(diǎn)故障問題。HA,如果主NameNode出現(xiàn)問題,切換到備用NN
(2)引入YARN
(3)使HDFS支持MapReduce之外的計(jì)算引擎
(4)解決內(nèi)存受限問題。聯(lián)邦HDFS,每個(gè)NameNode分管不同namespace,多NameNode合作,相互之間獨(dú)立,共享所有DataNode?,F(xiàn)在可OZONE替代hdfs。
Hadoop2.0 HA架構(gòu)角色
(1)主、備NameNode。同一時(shí)間只有一個(gè)主NameNode,可以有多個(gè)備NameNode。主備NameNode服務(wù)起在不同機(jī)器上。
(2)DataNode。同一時(shí)間向所有主備NameNode匯報(bào)block信息,但只接受主NameNode的命令。
(3)Journal node。主NameNode在Journal node集群上實(shí)時(shí)維護(hù)edits和fsimage,每一次編輯必須寫入多數(shù)Journal node。主備切換時(shí)備用NameNode從Journal node讀取文件,恢復(fù)元數(shù)據(jù)。同一時(shí)間QJN僅允許一個(gè)Namenode寫入日志。
(4)Failover controller。負(fù)責(zé)主備NameNode切換,對(duì)活躍NameNode進(jìn)行心跳檢查,確定是否真的失效了,也有active/standby之分,一個(gè)Failover controller對(duì)應(yīng)一個(gè)NameNode。
(5)Zookeeper。選舉活躍NameNode。active NameNode掛了之后,F(xiàn)ailover controller向zookeeper競爭鎖,競爭方法是投票,勝選NameNode當(dāng)選為active。必須為奇數(shù)個(gè)。
(6)client。請(qǐng)求zookeeper獲取主NameNode地址。
8. NameNode的目錄結(jié)構(gòu)
${dfs.namenode.name.dir}/
——————current
—————————————VERSION
—————————————edits_0000000000000000000001-00000000000000000000019
—————————————edits_inprogress_0000000000000000000020
—————————————fsimage_000000000000000000000
—————————————fsimage_000000000000000000000.md5
—————————————fsimage_000000000000000000019
—————————————fsimage_000000000000000000019.md5
—————————————seen_tx1d
———————in_use.lock
VERSION是一個(gè)Java屬性文件,包含正在運(yùn)行的hdfs版本信息。如果HDFS持久性數(shù)據(jù)結(jié)構(gòu)變更,HDFS則需要升級(jí),否則HDFS無法正常工作。
in_use.lock是一個(gè)鎖文件,namenode使用該文件為存儲(chǔ)目錄加鎖,避免其他namenode實(shí)例同時(shí)使用。
edits是編輯日志。文件系統(tǒng)客戶端執(zhí)行寫操作時(shí),會(huì)被記錄到編輯日志中。namenode在內(nèi)存中維護(hù)文系統(tǒng)的元數(shù)據(jù),當(dāng)編輯日志被修改時(shí),內(nèi)存中的元數(shù)據(jù)信息也被同步更新。edits在邏輯上是單個(gè)文件,但在磁盤上體現(xiàn)為多個(gè)文件,每個(gè)文件是一個(gè)segment。任意時(shí)刻只有一個(gè)文件處于可寫狀態(tài),即是名字中帶inprogress的那個(gè)。每個(gè)事務(wù)完成后,在向客戶端發(fā)送成功代碼前,都要更新edits文件。當(dāng)namenode向多個(gè)目錄寫數(shù)據(jù)時(shí),只有所有寫操作成功并更新到edits中時(shí)才會(huì)返回成功。
fsimage是文件系統(tǒng)映像。每個(gè)fsimage是文件系統(tǒng)元數(shù)據(jù)的一個(gè)完整的永久檢查點(diǎn)。因?yàn)閒simage是一個(gè)大型文件,不會(huì)頻繁更新,只是在和edits合并時(shí)更新。合并操作由secondary namenode完成,因此secondary namenode也需要大內(nèi)存。
9. DataNode目錄結(jié)構(gòu)
DataNode的存儲(chǔ)目錄是在初始階段自動(dòng)創(chuàng)建的,不需要額外格式化。
${dfs.datanode.data.dir}/
———current
————BP-526805057-127.0.0.1-1411808
—————————current
—————————VERSION
—————————finalized
—————————————blk_1073741825
—————————————blk_1073741825.meta
—————————————blk_1073741826
—————————————blk_1073741826.meta
——————————rbw
————VERSION
———in_use.lock
HDFS數(shù)據(jù)塊存儲(chǔ)在以blk為前綴的文件中,文件名包含了該文件塊的原始字節(jié)數(shù)。每個(gè)塊有一個(gè)相關(guān)聯(lián)的帶.meta后綴的元數(shù)據(jù)文件,元數(shù)據(jù)文件包括版本信息、類型信息和該數(shù)據(jù)塊的校驗(yàn)和。
10. HDFS的數(shù)據(jù)完整性
HDFS會(huì)對(duì)寫入的所有數(shù)據(jù)計(jì)算校驗(yàn)和,并在讀取數(shù)據(jù)時(shí)驗(yàn)證校驗(yàn)和。HDFS使用的是CRC-32C計(jì)算校驗(yàn)和,只占4個(gè)字節(jié),存儲(chǔ)校驗(yàn)和的額外開銷小于1%。
寫文件時(shí),客戶端計(jì)算校驗(yàn)和,并隨數(shù)據(jù)文件一起發(fā)送給DataNode管線,管線中的最后一個(gè)DataNode負(fù)責(zé)驗(yàn)證校驗(yàn)和。如果校驗(yàn)到錯(cuò)誤,客戶端會(huì)收到一個(gè)IOException異常。
讀文件時(shí),客戶端會(huì)驗(yàn)證DataNode發(fā)來的block校驗(yàn)和,如果成功驗(yàn)證,會(huì)將結(jié)果告知該DataNode。每個(gè)DataNode均持久保存一個(gè)校驗(yàn)和日志,收到客戶端的成功反饋,DataNode就會(huì)更新日志中的最新校驗(yàn)時(shí)間。
客戶端在讀取數(shù)據(jù)庫時(shí)若檢測到錯(cuò)誤,首先向namenode報(bào)告已損壞的數(shù)據(jù)塊和相應(yīng)的DataNode,namenode隨即將該DataNode的數(shù)據(jù)塊復(fù)本標(biāo)記為已損壞,這個(gè)DataNode將不再接受讀取損壞數(shù)據(jù)塊的請(qǐng)求。之后,namenode會(huì)將損壞數(shù)據(jù)塊的一個(gè)復(fù)本復(fù)制到另一個(gè)datanode上,恢復(fù)復(fù)本因子。此后,擇時(shí)刪除損壞數(shù)據(jù)塊。
11. HDFS序列化
序列化(serialization)是指將結(jié)構(gòu)化對(duì)象轉(zhuǎn)化為二進(jìn)制字節(jié)流以便在網(wǎng)絡(luò)上傳輸或?qū)懙酱疟P中進(jìn)行永久存儲(chǔ)的過程。反序列化(deserialization)則是將字節(jié)流恢復(fù)成對(duì)象的逆過程。
序列化用于分布式數(shù)據(jù)處理的兩個(gè)方面:進(jìn)程間通信和磁盤永久存儲(chǔ)。在Hadoop中,集群中多節(jié)點(diǎn)上的進(jìn)程間通信使用RPC協(xié)議。RPC協(xié)議將消息序列化成二進(jìn)制流后發(fā)送到遠(yuǎn)程節(jié)點(diǎn),遠(yuǎn)程節(jié)點(diǎn)將二進(jìn)制流反序列化為初始消息。Hadoop使用的是自定義的序列化格式writable,存放于org.apache.hadoop.io包中。大部分writable類都是對(duì)應(yīng)Java類型的擴(kuò)展,如int對(duì)應(yīng)intwritable,double對(duì)應(yīng)doublewritable,text對(duì)應(yīng)string。