終于有人把HDFS架構(gòu)和讀寫(xiě)流程講明白了
一、HDFS基礎(chǔ)
以下是HDFS設(shè)計(jì)時(shí)的目標(biāo)。
1. 硬件故障
硬件故障對(duì)于HDFS來(lái)說(shuō)應(yīng)該是常態(tài)而非例外。HDFS包含數(shù)百或數(shù)千臺(tái)服務(wù)器(計(jì)算機(jī)),每臺(tái)都存儲(chǔ)文件系統(tǒng)的一部分?jǐn)?shù)據(jù)。事實(shí)上,HDFS存在大量組件并且每個(gè)組件具有非平凡的故障概率,這意味著某些組件始終不起作用。因此,檢測(cè)故障并從中快速自動(dòng)恢復(fù)是HDFS的設(shè)計(jì)目標(biāo)。
2. 流式數(shù)據(jù)訪問(wèn)
在HDFS上運(yùn)行的應(yīng)用程序不是通常在通用文件系統(tǒng)上運(yùn)行的通用應(yīng)用程序,需要對(duì)其數(shù)據(jù)集進(jìn)行流式訪問(wèn)。HDFS用于批處理而不用于用戶的交互式使用,相對(duì)于數(shù)據(jù)訪問(wèn)的低延遲更注重?cái)?shù)據(jù)訪問(wèn)的高吞吐量。
可移植操作系統(tǒng)接口(Portable Operating System Interface of UNIX, POSIX)標(biāo)準(zhǔn)設(shè)置的一些硬性約束對(duì)HDFS來(lái)說(shuō)是不需要的,因此HDFS會(huì)調(diào)整一些POSIX特性來(lái)提高數(shù)據(jù)吞吐率,事實(shí)證明是有效的。
3. 超大數(shù)據(jù)集
在HDFS上運(yùn)行的應(yīng)用程序具有大型數(shù)據(jù)集。HDFS上的一個(gè)文件大小一般在吉字節(jié)(GB)到太字節(jié)(TB)。因此,HDFS需要設(shè)計(jì)成支持大文件存儲(chǔ),以提供整體較高的數(shù)據(jù)傳輸帶寬,能在一個(gè)集群里擴(kuò)展到數(shù)百上千個(gè)節(jié)點(diǎn)。一個(gè)HDFS實(shí)例需要支撐千萬(wàn)計(jì)的文件。
4. 簡(jiǎn)單的一致性模型
HDFS應(yīng)用需要“一次寫(xiě)入多次讀取”訪問(wèn)模型。假設(shè)一個(gè)文件經(jīng)過(guò)創(chuàng)建、寫(xiě)入和關(guān)閉之后就不會(huì)再改變了。這一假設(shè)簡(jiǎn)化了數(shù)據(jù)一致性問(wèn)題,并可實(shí)現(xiàn)高吞吐量的數(shù)據(jù)訪問(wèn)。MapReduce應(yīng)用或網(wǎng)絡(luò)爬蟲(chóng)應(yīng)用都非常適合這個(gè)模型。將來(lái)還需要擴(kuò)充這個(gè)模型,以便支持文件的附加寫(xiě)操作。
5. 移動(dòng)計(jì)算而不是移動(dòng)數(shù)據(jù)
當(dāng)應(yīng)用程序在其操作的數(shù)據(jù)附近執(zhí)行時(shí),計(jì)算效率更高。當(dāng)數(shù)據(jù)集很大時(shí)更是如此,這可以最大限度地減少網(wǎng)絡(luò)擁塞并提高系統(tǒng)的整體吞吐量。HDFS為應(yīng)用程序提供了接口,使其自身更靠近數(shù)據(jù)所在的位置。
6. 跨異構(gòu)硬件和軟件平臺(tái)的可移植性
HDFS的設(shè)計(jì)考慮到了異構(gòu)硬件和軟件平臺(tái)間的可移植性,方便了HDFS作為大規(guī)模數(shù)據(jù)應(yīng)用平臺(tái)的推廣。
從Hadoop這些年的發(fā)展來(lái)看,HDFS依靠上述特性,成為不斷演進(jìn)變革的大數(shù)據(jù)體系的堅(jiān)實(shí)基石。
二、HDFS架構(gòu)
HDFS是一個(gè)典型的主/備(Master/Slave)架構(gòu)的分布式系統(tǒng),由一個(gè)名字節(jié)點(diǎn)Namenode(Master) +多個(gè)數(shù)據(jù)節(jié)點(diǎn)Datanode(Slave)組成。其中Namenode提供元數(shù)據(jù)服務(wù),Datanode提供數(shù)據(jù)流服務(wù),用戶通過(guò)HDFS客戶端與Namenode和Datanode交互訪問(wèn)文件系統(tǒng)。
如圖3-1所示HDFS把文件的數(shù)據(jù)劃分為若干個(gè)塊(Block),每個(gè)Block存放在一組Datanode上,Namenode負(fù)責(zé)維護(hù)文件到Block的命名空間映射以及每個(gè)Block到Datanode的數(shù)據(jù)塊映射。
▲圖3-1 HDFS架構(gòu)
HDFS客戶端對(duì)文件系統(tǒng)進(jìn)行操作時(shí),如創(chuàng)建、打開(kāi)、重命名等,Namenode響應(yīng)請(qǐng)求并對(duì)命名空間進(jìn)行變更,再返回相關(guān)數(shù)據(jù)塊映射的Datanode,客戶端按照流協(xié)議完成數(shù)據(jù)的讀寫(xiě)。
- HDFS基本概念
HDFS架構(gòu)比較簡(jiǎn)單,但涉及概念較多,其中幾個(gè)重要的概念如下:
1. 塊(Block)
Block是HDFS文件系統(tǒng)處理的最小單位,一個(gè)文件可以按照Block大小劃分為多個(gè)Block,不同于Linux文件系統(tǒng)中的數(shù)據(jù)塊,HDFS文件通常是超大文件,因此Block大小一般設(shè)置得比較大,默認(rèn)為128MB。
2. 復(fù)制(Replica)
HDFS通過(guò)冗余存儲(chǔ)來(lái)保證數(shù)據(jù)的完整性,即一個(gè)Block會(huì)存放在N個(gè)Datanode中,HDFS客戶端向Namenode申請(qǐng)新Block時(shí),Namenode會(huì)根據(jù)Block分配策略為該Block分配相應(yīng)的Datanode replica,這些Datanode組成一個(gè)流水線(pipeline),數(shù)據(jù)依次串行寫(xiě)入,直至Block寫(xiě)入完成。
3. 名字節(jié)點(diǎn)(Namenode)
Namenode是HDFS文件系統(tǒng)的管理節(jié)點(diǎn),主要負(fù)責(zé)維護(hù)文件系統(tǒng)的命名空間(Namespace)或文件目錄樹(shù)(Tree)和文件數(shù)據(jù)塊映射(BlockMap),以及對(duì)外提供文件服務(wù)。
HDFS文件系統(tǒng)遵循POXIS協(xié)議標(biāo)準(zhǔn),與Linux文件系統(tǒng)類(lèi)似,采用基于Tree的數(shù)據(jù)結(jié)構(gòu),以INode作為節(jié)點(diǎn),實(shí)現(xiàn)一個(gè)目錄下多個(gè)子目錄和文件。INode是一個(gè)抽象類(lèi),表示File/Directory的層次關(guān)系,對(duì)于一個(gè)文件來(lái)說(shuō),INodeFile除了包含基本的文件屬性信息,也包含對(duì)應(yīng)的Block信息。
數(shù)據(jù)塊映射信息則由BlockMap負(fù)責(zé)管理,在Datanode的心跳上報(bào)中,將向Namenode匯報(bào)負(fù)責(zé)存儲(chǔ)的Block列表情況,BlockMap負(fù)責(zé)維護(hù)BlockID到Datanode的映射,以方便文件檢索時(shí)快速找到Block對(duì)應(yīng)的HDFS位置。
HDFS每一步操作都以FSEditLog的信息記錄下來(lái),一旦Namenode發(fā)生宕機(jī)重啟,可以從每一個(gè)FSEditLog還原出HDFS操作以恢復(fù)整個(gè)文件目錄樹(shù),如果HDFS集群發(fā)生過(guò)很多變更操作,整個(gè)過(guò)程將相當(dāng)漫長(zhǎng)。
因此HDFS會(huì)定期將Namenode的元數(shù)據(jù)以FSImage的形式寫(xiě)入文件中,這一操作相當(dāng)于為HDFS元數(shù)據(jù)打了一個(gè)快照,在恢復(fù)時(shí),僅恢復(fù)FSImage之后的FSEditLog即可。
由于Namenode在內(nèi)存中需要存放大量的信息,且恢復(fù)過(guò)程中集群不可用,HDFS提供HA(主/備N(xiāo)amenode實(shí)現(xiàn)故障遷移Failover)以及Federation(多組Namenode提供元數(shù)據(jù)服務(wù),以掛載表的形式對(duì)外提供統(tǒng)一的命名空間)特性以提高穩(wěn)定性和減少元數(shù)據(jù)壓力。
4. Datanode
Datanode是HDFS文件系統(tǒng)的數(shù)據(jù)節(jié)點(diǎn),提供基于Block的本地文件讀寫(xiě)服務(wù)。定期向Namenode發(fā)送心跳。Block在本地文件系統(tǒng)中由數(shù)據(jù)文件及元數(shù)據(jù)文件組成,前者為數(shù)據(jù)本身,后者則記錄Block長(zhǎng)度和校驗(yàn)和(checksum)等信息。掃描或讀取數(shù)據(jù)文件時(shí),HDFS即使運(yùn)行在廉價(jià)的硬件上,也能通過(guò)多副本的能力保證數(shù)據(jù)一致性。
5. FileSystem
HDFS客戶端實(shí)現(xiàn)了標(biāo)準(zhǔn)的Hadoop FileSystem接口,向上層應(yīng)用程序提供了各種各樣的文件操作接口,在內(nèi)部使用了DFSClient等對(duì)象并封裝了較為復(fù)雜的交互邏輯,這些邏輯對(duì)客戶端都是透明的。
三、HDFS讀寫(xiě)流程
1. HDFS客戶端寫(xiě)流程
圖3-2所示為客戶端完成HDFS文件寫(xiě)入的主流程。
▲圖3-2 客戶端完成HDFS寫(xiě)入的主流程
1)創(chuàng)建文件并獲得租約
HDFS客戶端通過(guò)調(diào)用DistributedFileSystem# create來(lái)實(shí)現(xiàn)遠(yuǎn)程調(diào)用Namenode提供的創(chuàng)建文件操作,Namenode在指定的路徑下創(chuàng)建一個(gè)空的文件并為該客戶端創(chuàng)建一個(gè)租約(在續(xù)約期內(nèi),將只能由這一個(gè)客戶端寫(xiě)數(shù)據(jù)至該文件),隨后將這個(gè)操作記錄至EditLog(編輯日志)。Namenode返回相應(yīng)的信息后,客戶端將使用這些信息,創(chuàng)建一個(gè)標(biāo)準(zhǔn)的Hadoop FSDataOutputStream輸出流對(duì)象。
2)寫(xiě)入數(shù)據(jù)
HDFS客戶端開(kāi)始向HdfsData-OutputStream寫(xiě)入數(shù)據(jù),由于當(dāng)前沒(méi)有可寫(xiě)的Block,DFSOutputStream根據(jù)副本數(shù)向Namenode申請(qǐng)若干Datanode組成一條流水線來(lái)完成數(shù)據(jù)的寫(xiě)入,如圖3-3所示。
▲圖3-3 流水線數(shù)據(jù)寫(xiě)入示意圖
3)串行寫(xiě)入數(shù)據(jù),直到寫(xiě)完Block
客戶端的數(shù)據(jù)以字節(jié)(byte)流的形式寫(xiě)入chunk(以chunk為單位計(jì)算checksum(校驗(yàn)和))。若干個(gè)chunk組成packet,數(shù)據(jù)以packet的形式從客戶端發(fā)送到第一個(gè)Datanode,再由第一個(gè)Datanode發(fā)送數(shù)據(jù)到第二個(gè)Datanode并完成本地寫(xiě)入,以此類(lèi)推,直到最后一個(gè)Datanode寫(xiě)入本地成功,可以從緩存中移除數(shù)據(jù)包(packet),如圖3-4所示。
▲圖3-4 串行寫(xiě)入數(shù)據(jù)示意圖
4)重復(fù)步驟2和步驟3,然后寫(xiě)數(shù)據(jù)包和回復(fù)數(shù)據(jù)包,直到數(shù)據(jù)全部寫(xiě)完。
5)關(guān)閉文件并釋放租約
客戶端執(zhí)行關(guān)閉文件后,HDFS客戶端將會(huì)在緩存中的數(shù)據(jù)被發(fā)送完成后遠(yuǎn)程調(diào)用Namenode執(zhí)行文件來(lái)關(guān)閉操作。
Datanode在定期的心跳上報(bào)中,以增量的信息匯報(bào)最新完成寫(xiě)入的Block,Namenode則會(huì)更新相應(yīng)的數(shù)據(jù)塊映射以及在新增Block或關(guān)閉文件時(shí)根據(jù)Block映射副本信息判斷數(shù)據(jù)是否可視為完全持久化(滿足最小備份因子)。
2. HDFS客戶端讀流程
相對(duì)于HDFS文件寫(xiě)入流程,HDFS讀流程相對(duì)簡(jiǎn)單,如圖3-5所示。
▲圖3-5 HDFS讀流程
1)HDFS客戶端遠(yuǎn)程調(diào)用Namenode,查詢(xún)?cè)獢?shù)據(jù)信息,獲得這個(gè)文件的數(shù)據(jù)塊位置列表,返回封裝DFSIntputStream的HdfsDataInputStream輸入流對(duì)象。
2)客戶端選擇一臺(tái)可用Datanode服務(wù)器,請(qǐng)求建立輸入流。
3)Datanode向輸入流中寫(xiě)原始數(shù)據(jù)和以packet為單位的checksum。
4)客戶端接收數(shù)據(jù)。如遇到異常,跳轉(zhuǎn)至步驟2,直到數(shù)據(jù)全部讀出,而后客戶端關(guān)閉輸入流。當(dāng)客戶端讀取時(shí),可能遇到Datanode或Block異常,導(dǎo)致當(dāng)前讀取失敗。正由于HDFS的多副本保證,DFSIntputStream將會(huì)切換至下一個(gè)Datanode進(jìn)行讀取。與HDFS寫(xiě)入類(lèi)似,通過(guò)checksum來(lái)保證讀取數(shù)據(jù)的完整性和準(zhǔn)確性。
本文摘編自《騰訊大數(shù)據(jù)構(gòu)建之道》,經(jīng)出版方授權(quán)發(fā)布。(ISBN:978-7-111-71076-9)?