您好,登錄后才能下訂單哦!
一、HDFS基本概念
HDFS全稱是Hadoop Distributed System。HDFS是為以流的方式存取大文件而設計的。適用于幾百MB,GB以及TB,并寫一次讀多次的場合。而對于低延時數據訪問、大量小文件、同時寫和任意的文件修改,則并不是十分適合。
目前HDFS支持的使用接口除了Java的還有,Thrift、C、FUSE、WebDAV、HTTP等。HDFS是以block-sized chunk組織其文件內容的,默認的block大小為64MB,對于不足64MB的文件,其會占用一個block,但實際上不用占用實際硬盤上的64MB,這可以說是HDFS是在文件系統之上架設的一個中間層。之所以將默認的block大小設置為64MB這么大,是因為block-sized對于文件定位很有幫助,同時大文件更使傳輸的時間遠大于文件尋找的時間,這樣可以最大化地減少文件定位的時間在整個文件獲取總時間中的比例。
二、HDFS設計原則
HDFS是Google的GFS(Google File System)的開源實現。具有以下五個基本目標:
1、硬件錯誤是常態而不是錯誤。HDFS一般運行在普通的硬件上,所以硬件錯誤是一種很正常的情況。所以在HDFS中,錯誤的檢測并快速自動恢復是HDFS的最核心的設計目標。
2、流式數據訪問。運行在HDFS上的應用主要是以批量處理為主,而不是用戶交互式事務,以流式數據讀取為多。
3、大規模數據集。HDFS中典型的文件大小要達到GB或者是TB級。
4、簡單一致性原則。HDFS的應用程序一般對文件的操作時一次寫入、多次讀出的模式。文件一經創建、寫入、關閉后,一般文件內容再發生改變。這種簡單的一致性原則,使高吞吐量的數據訪問成為可能。
5、數據就近原則。HDFS提供接口,以便應用程序將自身的執行代碼移動到數據節點上來執行。采用這種方式的原因主要是:移動計算比移動數據更加劃算。相比與HDFS中的大數據/大文件,移動計算的代碼相比與移動數據更加劃算,采用這種方式可以提供寬帶的利用率,增加系統吞吐量,減少網絡的堵塞程度。
三、HDFS的體系結構
構成HDFS主要是Namenode(master)和一系列的Datanode(workers)。
Namenode是管理HDFS的目錄樹和相關的文件元數據,這些信息是以"namespacep_w_picpath"和"edit log"兩個文件形式存放在本地磁盤,但是這些文件是在HDFS每次重啟的時候重新構造出來的。
Datanode則是存取文件實際內容的節點,Datanodes會定時地將block的列表匯報給Namenode。
由于Namenode是元數據存放的節點,如果Namenode掛了那么HDFS就沒法正常運行,因此一般使用將元數據持久存儲在本地或遠程的機器上,或者使用secondary namenode來定期同步Namenode的元數據信息,secondary namenode有點類似于MySQL的Master/Salves中的Slave,"edit log"就類似"bin log"。如果Namenode出現了故障,一般會將原Namenode中持久化的元數據拷貝到secondary namenode中,使secondary namenode作為新的Namenode運行起來。
HDFS是一個主從結構(master/slave)。如圖所示:
四、HDFS可靠性保障措施
HDFS的主要設計目標之一是在故障情況下,要保障數據存儲的可靠性。
HDFS具備了完善的冗余備份和故障恢復機制。一般通過dfs.replication設置備份份數,默認3。
1、冗余備份。將數據寫入到多個DataNode節點上,當其中某些節點宕機后,還可以從其他節點獲取數據并復制到其他節點,使備份數達到設置值。dfs.replication設置備份數。
2、副本存放。HDFS采用機架感知(Rack-aware)的策略來改進數據的可靠性、可用性和網絡寬帶的利用率。當復制因子為3時,HDFS的副本存放策略是:第一個副本放到同一機架的另一個節點(執行在集群中)/隨機一個節點(執行在集群外)。第二個副本放到本地機架的其他任意節點。第三個副本放在其他機架的任意節點。這種策略可以防止整個機架失效時的數據丟失,也可以充分利用到機架內的高寬帶特效。
3、心跳檢測。NameNode會周期性的從集群中的每一個DataNode上接收心跳包和塊報告,NameNode根據這些報告驗證映射和其他文件系統元數據。當NameNode沒法接收到DataNode節點的心跳報告后,NameNode會將該DataNode標記為宕機,NameNode不會再給該DataNode節點發送任何IO操作。同時DataNode的宕機也可能導致數據的復制。一般引發重新復制副本有多重原因:DataNode不可用、數據副本損壞、DataNode上的磁盤錯誤或者復制因子增大。
4、安全模式。在HDFS系統的時候,會先經過一個完全模式,在這個模式中,是不允許數據塊的寫操作。NameNode會檢測DataNode上的數據塊副本數沒有達到最小副本數,那么就會進入完全模式,并開始副本的復制,只有當副本數大于最小副本數的時候,那么會自動的離開安全模式。DataNode節點有效比例:dfs.safemode.threshold.pct(默認0.999f),所以說當DataNode節點丟失達到1-0.999f后,會進入安全模式。
5、數據完整性檢測。HDFS實現了對HDFS文件內容的校驗和檢測(CRC循環校驗碼),在寫入數據文件的時候,也會將數據塊的校驗和寫入到一個隱藏文件中()。當客戶端獲取文件后,它會檢查從DataNode節點獲取的數據庫對應的校驗和是否和隱藏文件中的校驗和一致,如果不一致,那么客戶端就會認為該數據庫有損壞,將從其他DataNode節點上獲取數據塊,并報告NameNode節點該DataNode節點的數據塊信息。
6、回收站。HDFS中刪除的文件先會保存到一個文件夾中(/trash),方便數據的恢復。當刪除的時間超過設置的時間閥后(默認6小時),HDFS會將數據塊徹底刪除。
7、映像文件和事務日志。這兩種數據是HDFS中的核心數據結構。
8、快照。
五、數據存儲操作
1、數據存儲: block
默認數據塊大小為128MB,可配置。若文件大小不到128MB,則單獨存成一個block。
為何數據塊如此之大? 數據傳輸時間超過尋道時間(高吞吐率)
一個文件存儲方式? 按大小被切分成若干個block,存儲到不同節點上,默認情況下每個block有三個副本。
2、數據存儲: staging
HDFSclient上傳數據到HDFS時,首先,在本地緩存數據,當數據達到一個block大小時,請求NameNode分配一個block。 NameNode會把block所在的DataNode的地址告訴HDFS client。 HDFS client會直接和DataNode通信,把數據寫到DataNode節點一個block文件中。
六、寫入數據
1.初始化FileSystem,客戶端調用create()來創建文件。
2.FileSystem用RPC調用元數據節點,在文件系統的命名空間中創建一個新的文件,元數據節點首先確定文件原來不存在,并且客戶端有創建文件的權限,然后創建新文件。
3.FileSystem返回DFSOutputStream,客戶端用于寫數據,客戶端開始寫入數據。
4.DFSOutputStream將數據分成塊,寫入data queue。data queue由Data Streamer讀取,并通知元數據節點分配數據節點,用來存儲數據塊(每塊默認復制3塊)。分配的數據節點放在一個pipeline里。Data Streamer將數據塊寫入pipeline中的第一個數據節點。第一個數據節點將數據塊發送給第二個數據節點。第二個數據節點將數據發送給第三個數據節點。
5.DFSOutputStream為發出去的數據塊保存了ack queue,等待pipeline中的數據節點告知數據已經寫入成功。
6.當客戶端結束寫入數據,則調用stream的close函數。此操作將所有的數據塊寫入pipeline中的數據節點,并等待ack queue返回成功。最后通知元數據節點寫入完畢。
7.如果數據節點在寫入的過程中失敗,關閉pipeline,將ack queue中的數據塊放入data queue的開始,當前的數據塊在已經寫入的數據節點中被元數據節點賦予新的標示,則錯誤節點重啟后能夠察覺其數據塊是過時的,會被刪除。失敗的數據節點從pipeline中移除,另外的數據塊則寫入pipeline中的另外兩個數據節點。元數據節點則被通知此數據塊是復制塊數不足,將來會再創建第三份備份。
8.如果在寫的過程中某個datanode發生錯誤,會采取以下幾步:
1)pipeline被關閉掉;
2)為了防止防止丟包ack quene里的packet會同步到data quene里;
3)把產生錯誤的datanode上當前在寫但未完成的block刪掉;
4)block剩下的部分被寫到剩下的兩個正常的datanode中;
5)namenode找到另外的datanode去創建這個塊的復制。當然,這些操作對客戶端來說是無感知的。
Java代碼
Configuration conf = new Configuration(); FileSystem fs = FileSystem.get(conf); Path file = new Path("demo.txt"); FSDataOutputStream outStream =fs.create(file); outStream.writeUTF("Welcome to HDFSJava API!!!"); outStream.close();
寫入過程圖片:
七、讀取過程
1.初始化FileSystem,然后客戶端(client)用FileSystem的open()函數打開文件。
2.FileSystem用RPC調用元數據節點,得到文件的數據塊信息,對于每一個數據塊,元數據節點返回保存數據塊的數據節點的地址。
3.FileSystem返回FSDataInputStream給客戶端,用來讀取數據,客戶端調用stream的read()函數開始讀取數據。
4.DFSInputStream連接保存此文件第一個數據塊的最近的數據節點,data從數據節點讀到客戶端(client)
5.當此數據塊讀取完畢時,DFSInputStream關閉和此數據節點的連接,然后連接此文件下一個數據塊的最近的數據節點。
6.當客戶端讀取完畢數據的時候,調用FSDataInputStream的close函數。
7.在讀取數據的過程中,如果客戶端在與數據節點通信出現錯誤,則嘗試連接包含此數據塊的下一個數據節點。
8. 失敗的數據節點將被記錄,以后不再連接。
Java代碼
Configurationconf = new Configuration(); FileSystemfs = FileSystem.get(conf); Pathfile = new Path("demo.txt"); FSDataInputStreaminStream = fs.open(file); Stringdata = inStream.readUTF(); System.out.println(data); inStream.close();
讀取文件過程圖片:
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。