客戶端讀寫hdfs數據

讀:前端

                            
       

   (1)客戶端經過調用FIleSystem對象的open()方法來打開但願讀取的文件,對於hdfs來講,這個對象是分佈式文件系統的一個實例。node

   (2)DistributedFileSystem經過使用rpc來調用namenode,以肯定文件起始塊的位置。對於每個塊,namenode返回存有該塊副本的datanode的地址。此外,這些datanode根據他們與客戶端的距離來排序(機架感應)。若是該客戶端自己就是一個datanode(好比,在一個MapReduce任務中),並保存有相應數據塊的一個副本時,該節點將從本地datanode中讀取數據。併發

    (3)DistributedFileSystem類返回一個FSDataInputStream對象(支持文件定位的輸入流)給客戶端讀取數據。FSDataInput類轉而封裝DFSInputStream對象,該對象管理着datanode、namenode的I/O。接着,客戶端對這個輸入流調用read()方法。分佈式

    (4)存儲着文件起始塊的datanode地址的DFSInputStream 隨即鏈接距離最近的文件中第一個塊所在的datanode。經過對數據流反覆調用read()方法,能夠將數據從datanode傳輸到客戶端。函數

    (5)到達塊的末端時,DFSInputStream 會關閉與該datanode的鏈接,而後尋找下一個塊的最佳datanode。客戶端只須要讀取連續的流,而且對於客戶端都是透明的。客戶端從流中讀取數據時,塊是按照打開DFSInputStream與datanode新建鏈接的順序讀取的。它根據須要詢問namenode來檢索下一批所需塊的datanode的位置。oop

    (6)一旦客戶端讀取完成,就對FSDataInputStream調用close()方法,在讀取數據的時候,若是DFSInputStream在與datanode通訊時遇到錯誤,它便嘗試從這個塊的另一個最鄰近的datanode讀取數據。它也會記住哪一個故障的datanode,以保證之後不會反覆讀取該節點上後續的塊。DFSInputStream也會經過校驗和確認從datanode發來的數據是否完整。若是發現一個損壞的塊,它就會在DFSInputStream 試圖從其餘datanode讀取一個塊的副本,也會將被損壞的塊通知給namonode。設計

        這個設計的一個重點是,客戶端能夠直接鏈接到datanode檢索數據,且namenode告訴客戶端每一個塊中的最佳datanode。因爲數據流分散在該集羣中全部的datanode,因此這種設計能使HDFS可擴展到大量的併發客戶端。同時,namenode僅須要響應快位置的請求(這些信息存儲在內存中,於是很是高效),而無需響應數據請求,不然隨着客戶端數量的增加,namenode很快會成爲一個瓶頸。對象

 

hadoop寫:blog

                            

(1)客戶端經過對DistributeFileSystem 對象調用create()函數來建立文件。排序

(2)DistributedFileSystem 對namenode建立一個rpc調用,在文件系統的命名空間中建立一個新文件,可是此時該文件中尚未相應的數據塊,namenode執行各個不一樣的檢查以確保這個文件不存在,而且客戶端有建立該文件的權限。若是這些檢查均經過,namenode就會爲建立新文件記錄一條記錄,不然,文件建立失敗並向客戶端拋出一個IoException異常。

(3)DistributeFileSystem向客戶端返回一個FSDataOutrputStream對象,由此客戶端能夠開始寫入數據。就像讀取事件同樣,FSDataOutputStream封裝一個DFSoutputstream對象,該對象負責處理datanode和namenode之間的通訊。在客戶端寫入數據時,DFSoutputStream將它分紅一個個的數據包,並寫入內部隊列,成爲數據隊列(data queue)

(4)dataStreamer處理數據隊列,它的責任是根據datanode列表來要求namenode分配適合的新塊來存儲數據備份。這一組datanode構成一個管道(pip管道)---咱們假設副本數是3,因此管道中有3個節點。dataStream將數據包流式傳輸到管道中第一個datanode,該datanode存儲數據包以後,並將它發送到管道中第二個datanode中,一樣操做,第二個datanode 將數據包存儲後給第三個datanode。

(5)DFSOoutputStream也維護着一個內部數據包隊列來等待datanode的收到確認回執,稱爲"確認隊列"(ack queue)。當收到管道中全部的datanode確認信息後,該數據包纔會從確認隊列刪除。

    若是在數據寫入期間,datanode發生故障,則執行如下操做,這對與寫入數據的客戶端是透明的。首先關閉管道,確認把隊列中的任何數據包都添回數據隊列的最前端,以確保故障節點下游的datanode不會漏掉任何一個數據包。爲存儲在另外一個正常datanode的當前數據塊制定一個新的標識,並將該標識傳送給namenode。以便故障datanode在恢復後能夠刪除存儲的部分數據塊。從管道中刪除故障數據節點而且把餘下的數據塊寫入管道中剩餘的兩個正常的datanode。namenode注意到塊副本量不足時,會在另外一個節點上建立一個新的副本。後續的數據塊繼續正常接受處理。

(6)客戶端完成數據的寫入後,會對數據流調用close()方法。

(7)該操做將剩餘的全部數據包寫入datanode管道中,並在聯繫namenode發送文件寫入完成信號以前,等待確認。namenode已經知道文件由哪些塊組成(經過DataStreamer詢問數據塊的分配),因此它在返回成功只須要等待數據塊進行最小量的複製。

相關文章
相關標籤/搜索