HDFS讀寫數據流程


HDFS讀寫數據流程

標簽(空格分隔): Apache Hadoop


HDFS是hadoop重要的組件之一,對其進行數據的讀寫是很常見的操作,然而真的了解其讀寫過程嗎?

前言

HDFS – Hadoop Distributed File System,是hadoop的存儲層,它參照google的GFS思想實現。

它以master-slave工作。NameNode作為master daemon,工作在master node上,DataNode作為slave daemon,工作在slave node上。master 之間在 HDFS 2.X.X 版本實現HA 高可用。

一,寫HDFS

1. 流程圖

image.png-224.3kB

2. 重要概念

HDFS一個文件由多個block構成。或者說一個文件會被切分成按照HDFS block 大小的多個塊去存儲。

HDFS在進行block讀寫的時候是以packet(默認每個packet為64K)為單位進行的。

每一個packet由若干個chunk(默認512Byte)組成。Chunk是進行數據校驗的基本單位,對每一個chunk生成一個校驗和(默認4Byte)並將校驗和進行存儲。

在寫入一個block的時候,數據傳輸的基本單位是packet,每個packet由若干個chunk組成。

3. 過程步驟

1) HDFS client發送一個create請求給DistributedFileSystem API

2)DistributedFileSystem 使用一個RPC請求,通知NameNode在其命名空間創建一個新文件(會遇到全局鎖,后續會講到)。

此時,NameNode會進行一系列的check,如是否有權限,文件是否已經存在。 當通過check后,NameNode創建一個新的文件,狀態為under construction,沒有任何data block與之對應,否則,拋出一個IO異常

3)DistributedFileSystem 返回一個 FSDataOutputStream 給client,讓它開始寫入數據。

FSDataOutputStream的成員變量dfs類型為DFSClient,DFSClient在創建時,會構造一個DFSOutputStream。 當client開始寫數據時, DFSOutputStream 會將file分割成 packets,然后把 packets都放在一個隊列中,這個隊列叫做data queue。 data queue會被DataStreamer消費。DataStreamer的負責就是,通過挑選一系列合適的datanode來存儲副本,從而要求NameNode分配新的blocks。

4)一系列合適的datanode 表現為一個pipeline。假如此時備份級別是3,那么在pipeline中就有3個node。 DataStreamer將這些packets以流式傳入pipeline中的第一個datanode。 這些packets將會存儲在第一個datanode中。 然后因為第一個datanode中存放了第二個datanode的地址,所以它會在接收client傳來的下一個packet時,會將自己已經收到的packet寫入第二個datanode中。 以此類推,每個datanode在接收上級(client或者datanode)的寫時,自己也會擔負起寫下級datanode的責任。 所以這樣看來,packet對datanode的寫,其實是並行的。

5)DFSOutputStream同時也維護了一個內部隊列,叫做ack queue,它里面存放了所有要被datanodes確認的packets。 只有當一個packet被pipeline中的datanodes確認后,這個packet才會從ack queue中刪除。 一旦需要的副本數量被創建,datanodes就會發送acknowledgment。

6)當client結束了寫數據,它會在流上調用一個close()。

7) 這個close的動作,會flush所有剩余的packets到datanodes pipeline中,然后等待datanodes的acknowledgments,最后給namenode發信號說文件已完成。 namenode已經知道了文件是由哪些block組成的,所以在返回成功之前,它只需要等待那些塊被最小的備份就可以了。

4. 容錯過程

這部分 是大部分人比較忽視的。
當在向 datanode 寫入數據失敗時,將執行以下操作,這些操作對於寫入數據的客戶端是透明的。

首先,關閉管道,並將ack隊列中的任何數據包添加到數據隊列的前面,以便故障節點下游的數據節點不會丟失任何數據包。
當前塊的 datanode 如果是良好的話,這個塊會被賦予一個新的標識,該標識被傳送到 namenode,以便如果稍后恢復失敗的 datanode 時,可以將失敗的 datanode 上的失敗塊刪除。
datanode 失敗的話,它將從管道中刪除,然后塊的其余數據將寫入管道中的兩個良好數據節點。
namenode 注意到該塊未被復制,並且它安排在另一個節點上創建另一個副本,然后它將后續塊視為正常。
客戶端寫入塊時,多個數據節點失敗是可能的, 只要它寫入dfs.replication.min(默認為1),寫入就會成功,並且該塊將在群集中異步復制,直到達到目標復制因子(dfs.replication,默認為3)。異步復制線程會在namenode 5min 啟動一次。將需要復制的塊添加到復制隊列。

二,讀HDFS

1. 流程圖

image.png-201.8kB

2. 過程步驟

1) client 讀取目標文件,是通過一個FileSystem對象的open()方法。這個FileSystem對象,對HDFS來講,就是一個DistributedFileSystem。

2)DistributedFileSystem 使用一個RPC請求,詢問NameNode文件前幾個block的位置。

對於每個block,namenode會根據就近原則,返回那些離client較近(根據friendly 去計算塊的距離遠近),而且也存儲了該block的datanode地址。

3)DistributedFileSystem 返回一個 FSDataInputStream給client,讓client通過它來讀取文件。

FSDataOutputStream包裹了一個DFSInputStream。DFSInputStream會來管理與datanode和namenode的I/O。 client在流上調用read()。已經存儲了datanode地址的DFSInputStream,接着就會連接存儲文件第一個block的、且距離最近的datanode。

4)數據會以流式傳回client,因此client可以在流上重復調用read。 當這個block結束后,DFSInputStream會關閉和datanode的連接,然后找到對下個block而言最好的datanode。

5)如果DFSInputStream在和datanode交流時,發生了錯誤,它就會嘗試下一個離它最近的datanode。 DFSInputStream會記下那些失敗的datanodes,以免之后的block們對它們不必要的請求。 DFSInputStream同時會對從datanode傳回的數據進行驗證。如果它發現了損壞的block,它想namenode報告這個情況,然后再去請求詞block的下一個備份的datanode。

6)當client結束了讀數據,它會在流上調用一個close()。

參考鏈接

Hadoop HDFS Data Read and Write Operations: https://data-flair.training/blogs/hadoop-hdfs-data-read-and-write-operations/
HDFS讀寫文件流程: https://blog.csdn.net/qq_20641565/article/details/53328279
HDFS dfsclient寫文件過程 源碼分析: http://www.cnblogs.com/ggjucheng/archive/2013/02/19/2917020.html


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM