HDFS讀寫流程解析

1、HDFS文件讀寫流程
? 1.1、剖析文件讀取過程
? 1.2、剖析文件寫入過程


1、HDFS文件讀寫流程:

作為一個文件系統(tǒng),文件的讀和寫是最基本的需求,這一部分我們來了解客戶端是如何與HDFS進(jìn)行交互的,也就是客戶端與HDFS,以及構(gòu)成HDFS的兩類節(jié)點(diǎn)(namenode和datanode)之間的數(shù)據(jù)流是怎樣的。

1.1、剖析文件讀取過程:

客戶端從HDFS讀取文件,其內(nèi)部的讀取過程實際是比較復(fù)雜的,可以用下圖來表示讀取文件的基本流程。
對于客戶端來說,首先是調(diào)用FileSystem對象的open()方法來打開希望讀取的文件,然后HDFS會返回一個文件輸入流FSDataInputStream ,客戶端對這個輸入流調(diào)用read()方法,讀取數(shù)據(jù),一旦完成讀取,就對這個輸入流調(diào)用close()方法關(guān)閉,這三個過程對應(yīng)圖中的步驟1、3、6。

以上三個步驟是從客戶端的角度來分析的,實際上,要實現(xiàn)文件讀取,HDFS內(nèi)部還需要比較復(fù)雜的機(jī)制來支持,而這些過程都是對客戶端透明的,所以客戶端感受不到,在客戶看來就像是在讀取一個連續(xù)的流。


hdfs-3.png

具體的,從HDFS的角度來說:

  • 客戶端調(diào)用的FileSystem對象的open()方法,這個FileSystem對象實際上是分布式文件系統(tǒng)DistributedFileSystem的一個實例,DistributedFileSystem通過遠(yuǎn)程過程調(diào)用(RPC)來調(diào)用namenode,以獲得文件起始塊的位置(步驟2,namenode返回存有該數(shù)據(jù)塊副本的datanode的地址)。當(dāng)然,由于HDFS保存了一個數(shù)據(jù)塊的多個副本(默認(rèn)是3),所以滿足請求的datanode地址不止一個,此時會根據(jù)它們與客戶端的距離來排序,優(yōu)先選擇距離近的datanode,如果該客戶端本身就是一個datanode,該客戶端就可以從本地讀取數(shù)據(jù)(比如:mapReduce就利用了這里的數(shù)據(jù)本地化優(yōu)勢)。
  • open方法完成后,DistributedFileSystem類返回一個FSDataInputStream(支持文件定位的輸入流)對象給客戶端以便于讀取數(shù)據(jù)。這個類轉(zhuǎn)而封裝為DFSInputStream對象,該對象管理著datanode和namenode的I/O。
  • 這個DFSInputStream存儲著文件起始幾個塊的datanode地址,因此,客戶端對這個輸入流調(diào)用read()方法就可以知道到哪個datanode(網(wǎng)絡(luò)拓?fù)渲芯嚯x最近的)去讀取數(shù)據(jù),這樣,反復(fù)調(diào)用read方法就可以將數(shù)據(jù)從datanode傳輸?shù)娇蛻舳耍ú襟E4)。到達(dá)一個塊的末端時,會關(guān)閉和這個datanode的連接,尋找下一個塊的最佳datanode,重復(fù)這個過程。

當(dāng)然,上面我們說DistributedFileSystem只存儲著文件起始的幾個塊,在讀取過程中,也會根據(jù)需要再次詢問namenode來獲取下一批數(shù)據(jù)塊的datanode地址。一旦客戶端讀取完成,就調(diào)用close方法關(guān)閉數(shù)據(jù)流。

如果在讀取過程中,datanode遇到故障,很明顯,輸入流只需要從另外一個保存了該數(shù)據(jù)塊副本的最近datanode讀取即可,同時記住那個故障datanode,以后避免從那里讀取數(shù)據(jù)。

總結(jié):
以上就是HDFS的文件讀取過程,從這個過程的分析中我們可以看出:其優(yōu)勢在于客戶端可以直接連接到datanode進(jìn)行數(shù)據(jù)的讀取,這樣由于數(shù)據(jù)分散在不同的datanode上,就可以同時為大量并發(fā)的客戶端提供服務(wù)。而namenode作為管理節(jié)點(diǎn),只需要響應(yīng)數(shù)據(jù)塊位置的請求,告知客戶端每個數(shù)據(jù)塊所在的最佳datanode即可(datanode的位置信息存儲在內(nèi)存中,非常高效的可以獲?。?。這樣使得namenode無需進(jìn)行具體的數(shù)據(jù)傳輸任務(wù),否則namenode在客戶端數(shù)量多的情況下會成為瓶頸。

1.2、剖析文件寫入過程:

接下來我們分析文件寫入的過程,重點(diǎn)考慮的情況是如何新建一個文件、如何將數(shù)據(jù)寫入文件并最后關(guān)閉該文件。


hdfs-4.png

然而,具體的,從HDFS的角度來看,這個寫數(shù)據(jù)的過程就相當(dāng)復(fù)雜了:

  1. 首先客戶端通過DistributedFileSystem上的create()方法指明一個預(yù)創(chuàng)建的文件的文件名;
  2. DistributedFileSystem會對namenode創(chuàng)建一個RPC調(diào)用,在文件系統(tǒng)的命名空間中新建一個文件,此時還沒有相應(yīng)的數(shù)據(jù)塊(步驟2)。namedata接收到這個RPC調(diào)用后,會進(jìn)行一系列的檢查,確保這個文件不存在,并且這個客戶端有新建文件的權(quán)限,如果檢查通過,namenode會為該文件創(chuàng)建一個新的記錄,否則的話文件創(chuàng)建失敗,客戶端得到一個IOException異常,最后DistributedFileSystem返回一個FSDataOutputStream以供客戶端寫入數(shù)據(jù),與FSDataInputStream類似,F(xiàn)SDataOutputStream封裝了一個DFSOutputStream用于處理namenode與datanode之間的通信;
  3. 當(dāng)客戶端開始寫數(shù)據(jù)時(DFSOutputStream把寫入的塊數(shù)據(jù)時會將其拆分成64k的數(shù)據(jù)包(packet), 放入一個中間隊列——數(shù)據(jù)隊列(data queue)中去。DataStreamer從數(shù)據(jù)隊列中取數(shù)據(jù),同時向namenode申請一個新的block來存放它已經(jīng)取得的數(shù)據(jù)。namenode選擇一系列合適的datanode(個數(shù)由文件的replica數(shù)決定)構(gòu)成一個管道線(pipeline),這里我們假設(shè)replica為3,所以管道線中就有三個datanode;
  4. DataSteamer把數(shù)據(jù)流式的寫入到管道線中的第一個datanode中,第一個datanode再把接收到的數(shù)據(jù)轉(zhuǎn)到第二個datanode中,以此類推;
  5. DFSOutputStream同時也維護(hù)著另一個中間隊列——確認(rèn)隊列(ack queue),確認(rèn)隊列中的包只有在得到管道線中所有的datanode的確認(rèn)以后才會被移出確認(rèn)隊列。上面的DataStreamer 線程會從 dataQueue 隊列中取出 Packet 對象,通過底層 IO 流發(fā)送到 pipeline 中的第一個 DataNode,然后繼續(xù)將所有的包轉(zhuǎn)到第二個 DataNode 中,以此類推。發(fā)送完畢后,這個 Packet 會被移出 dataQueue,放入 DFSOutputStream 維護(hù)的確認(rèn)隊列 ackQueue 中,該隊列等待下游 DataNode 的寫入確認(rèn)。當(dāng)一個包已經(jīng)被 pipeline 中所有的 DataNode 確認(rèn)了寫入磁盤成功,這個數(shù)據(jù)包才會從確認(rèn)隊列中移除;

如果某個datanode在寫數(shù)據(jù)的時候掛掉了,下面這些對用戶透明的步驟會被執(zhí)行:

  • 管道線關(guān)閉,所有確認(rèn)隊列上的數(shù)據(jù)會被挪到數(shù)據(jù)隊列的首部重新發(fā)送,這樣可以確保管道線中掛掉的datanode下游的datanode不會因為掛掉的datanode而丟失數(shù)據(jù)包;
  • 在還在正常運(yùn)行的datanode上的當(dāng)前block上做一個標(biāo)志,這樣當(dāng)掛掉的datanode重新啟動以后namenode就會知道該datanode上哪個block是剛才宕機(jī)時殘留下的局部損壞block,從而可以把它刪掉;
  • 已經(jīng)掛掉的datanode從管道線中被移除,未寫完的block的其他數(shù)據(jù)繼續(xù)被寫入到其他兩個還在正常運(yùn)行的datanode中去,namenode知道這個block還處在under-replicated狀態(tài)(也即備份數(shù)不足的狀態(tài))下,然后他會安排一個新的replica從而達(dá)到要求的備份數(shù),后續(xù)的block寫入方法同前面正常時候一樣。有可能管道線中的多個datanode掛掉(雖然不太經(jīng)常發(fā)生),但只要dfs.replication.min(默認(rèn)為1)個replica被創(chuàng)建,我們就認(rèn)為該創(chuàng)建成功了。剩余的replica會在以后異步創(chuàng)建以達(dá)到指定的replica數(shù);
  1. 當(dāng)客戶端完成寫數(shù)據(jù)后,它會調(diào)用close()方法。這個操作會沖洗(flush)所有剩下的package到pipeline中。

  2. 等待這些package確認(rèn)成功,然后通知namenode寫入文件成功。這時候namenode就知道該文件由哪些block組成(因為DataStreamer向namenode請求分配新block,namenode當(dāng)然會知道它分配過哪些blcok給給定文件),它會等待最少的replica數(shù)被創(chuàng)建,然后成功返回。

注意:hdfs在寫入的過程中,有一點(diǎn)與hdfs讀取的時候非常相似,就是"DataStreamer在寫入數(shù)據(jù)的時候,每寫完一個datanode的數(shù)據(jù)塊,都會重新向nameNode申請合適的datanode列表。這是為了保證系統(tǒng)中datanode數(shù)據(jù)存儲的均衡性"。

hdfs寫入過程中,datanode管線的確認(rèn)應(yīng)答包并不是每寫完一個datanode,就返回一個確認(rèn)應(yīng)答,而是一直寫入,直到最后一個datanode寫入完畢后,統(tǒng)一返回應(yīng)答包。如果中間的一個datanode出現(xiàn)故障,那么返回的應(yīng)答就是前面完好的datanode確認(rèn)應(yīng)答,和故障datanode的故障異常。這樣我們也就可以理解,在寫入數(shù)據(jù)的過程中,為什么數(shù)據(jù)包的校驗是在最后一個datanode完成。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • 我們在上一篇《分布式文件系統(tǒng)HDFS——基礎(chǔ)篇》中已經(jīng)已經(jīng)對HDFS的基本概念和操作進(jìn)行了介紹,這一次我們將要更深...
    愛做夢的錘子閱讀 790評論 0 1
  • HDFS讀寫流程剖析 本文為 《Hadoop The Definitive Guide 4th Edition》的...
    希爾大閱讀 3,876評論 0 2
  • 隨著數(shù)據(jù)量越來越大, 在 一個操作系統(tǒng)管轄的范圍存不下了, 那么就 分配到更多的操作系統(tǒng)管理的磁盤中, 但是不方便...
    tracy_668閱讀 2,886評論 0 6
  • HDFS的寫數(shù)據(jù)流程 1)客戶端通過DistributedFileSystem模塊想NameNode請求上傳文件,...
    codeMover閱讀 1,128評論 0 3
  • 本文章主題: 寫流程 讀流程 HDFS遵循一次寫入多次讀取的原則,因此已經(jīng)寫入文件系統(tǒng)的文件是無法修改的,只能進(jìn)行...
    JustCode閱讀 1,400評論 0 1

友情鏈接更多精彩內(nèi)容