好程式設計師大資料學習路線分享分散式檔案系統HDFS

好程式設計師IT發表於2019-08-22

好程式設計師大資料學習路線分享 分散式檔案系統HDFS,設計目標:

1 儲存量大

2 自動快速檢測應對硬體錯誤

3 流式訪問資料

4 移動計算比移動資料本身更划算

5 簡單一致性模型

6 異構平臺可移植

特點

優點:

  1. 高可靠性:Hadoop 按位儲存和處理資料的能力強
  2. 高擴充套件性:hadoop 是在可用的計算機集簇間分配資料並完成計算任務的,這些集簇可以方便地擴充套件到數以千計的節點中
  3. 高效性:hadoop 能夠在節點之間動態地移動資料,並保證各個節點的動態平衡,因此處理速度非常快
  4. 高容錯性:hadoop 能夠自動儲存資料的多個副本,並且能夠自動將失敗的任務重新分配。

缺點:

  1. 不適合低延遲資料訪問
  2. 無法高效儲存大量小檔案(每個檔案儲存都有屬於自己的索引, 後設資料龐大就不高效)
  3. 不支援多使用者寫入及任意修改檔案(可以刪除以及追加,只是不能修改檔案中某處的資料)

重要特性:

  1. 檔案在物理上是分塊儲存,塊的大小可以透過配置引數(dfs.blocksize) 來規定, 預設 2.x 版本之後是 128M ,老版本是64M
  2. HDFS 會給哭護短提供一個統一的 抽象目錄樹 ,客戶端透過路徑來訪問檔案, 刑辱: hdfs://namenode:port/dir-a/dir-b/dir-c/file.data
  3. 目錄結構及檔案分塊資訊( 後設資料 ) 的管理由namenode 承擔—namenode HDFS 叢集主節點,負責維護整個 hdfs 檔案系統的目錄樹,以及每一個路徑(檔案)所對應的 block 塊資訊( block id 以及所在 datanode 伺服器)
  4. 檔案的各個block 的儲存管理由 datanode 承擔—datanode HDFS 叢集從節點,每一個 block 都可以在多個 datanode 上儲存多個副本(副本引數設定 dfs.replication)
  5. HDFS 是設計成適應一次寫入, 多次讀出的場景, 且不支援檔案的修改
  6. 管理檔案系統的名稱空間( 後設資料<metadata>:包含檔名稱、大小、所屬人、地址)
  7. 規定客戶端訪問檔案規則

三個服務

Namenode
任務清單

a)  檔案大小是否已經超載( 超過叢集的負載)

b)  是否已經存在相同的檔案

c) 是否具有建立該檔案的許可權

  1. 對檔案執行命令,關閉,開啟檔案或者開啟路徑等操作
  2. 所有的資料節點傳送心跳給NameNode ,他需要確保資料節點 DataNode 是否線上,一個資料塊報告包含所有這個資料節點上的所有 block 的狀況
  3. 首先將fsimage(映象) 載入記憶體,並讀取執行日誌editlog 的各項操作
  4. 一旦在記憶體中建立檔案系統後設資料對映,則建立一個新的fsimage 檔案(這個過程不需要 secondaryNamenode )和一個空的 editlog
  5. 在安全模式下,各個datanode 會向 namenode 傳送塊列表的最新情況
  6. 此刻namenode 執行在安全模式。即 NameNode 的檔案系統對於客戶端來說是隻讀
  7. NameNode 開始監聽 RPC HTTP 請求
啟動過程

RPC:Remote Procedure Call Protocol---遠端過程透過協議

它是一種透過網路從遠端計算機程式上請求服務,而不需要了解底層網路技術的協議

  1. 系統中資料塊的位置並不是由namenode 維護的 , 而是以塊列表形式儲存在 datanode
  2. 在系統的正常操作期間,namenode 會在記憶體中保留所有塊資訊的對映資訊
  3. fsimage:後設資料映象檔案(儲存檔案系統的目錄樹)
  4. edit.log: 後設資料操作日誌( 針對目錄樹的修改操作)
兩個重要檔案
後設資料映象

a) 記憶體中儲存一份最新的

b)  記憶體中映象=fsimage+edits

SecondaryNamenode
工作任務

定期合併fsimage edits

c) Edits 檔案過大將導致 NamenNode 重啟速度緩慢

d) SecondaryNameNode 負責定期合併他們

 

Datanode


hdfs 的寫過程


寫過程語言Description :
  1. Client 透過呼叫 FileSystem get 方法與 namenode 程式建立通道進行通訊,然後呼叫 create 方法來請求建立檔案。
  2. FileSystem 透過對 namenode 發出遠端請求,在 namenode 裡面建立一個新的檔案,但此時並不關聯任何的塊。 NameNode 進行很多檢查來保證不存在要建立的檔案已經存在檔案系統中,同時檢查是否有相應的許可權來建立檔案。如果這些檢查完了, nameNameNode 將這個新檔案的嘻嘻記錄下來,然後 FileSystem 返回一個 DFSOutputStream 給客戶端用來寫入資料。和讀的情形一樣, FSDataOutputStream 將包裝一個 DFSOutputStream 用於和 DataNode NameNode 通訊。而一旦檔案建立失敗,客戶端會受到一個 IOException,標識檔案建立失敗,停止後續任務。
  3. 客戶端開始寫數。FSDataOutputStream 把要寫入的資料分成塊打成包的形式,將其寫入到 DFSOutputStream 物件的中間佇列中。其中的資料由 Datastreamer 來讀取。DataStreamer 的職責是讓NameNode 分配新的塊找出合適的DataNode 來儲存作為備份而複製的資料。
  4. FSDataOutputStream 維護了一個內部關於 packets 的佇列,裡面存放等待被 DataNode 確認無誤的 packets 的資訊。這個佇列被稱為等待佇列,一個 packet 的資訊被移出本佇列當且僅當 packet 被所有節點都確認無誤。
  5. 當完成資料寫入之後客戶端呼叫流的close 方法,再通知 NameNode 完成寫入之前,這個方法將 flush 殘留的 packets ,並等待確認資訊。 NameNode 已經知道檔案由哪些塊組成,所以在返回成功前只需要等待資料塊進行最小複製。
Write  API :
1 . 從本地系統上傳到hdfs

Configuration hdfsConf = new Configuration();// 建立一個hdfs 的環境變數

String namenodeURI=”hdfs://hadoop001:8020”;//namenode的統一資源定位符

String username=”root”;// 訪問指定使用者的hdfs

FileSystem hdfs = FileSystem.get(new URI(namenodeURI),hdfsConf,username);// 建立一個hdfs 的檔案系統物件

FileSystem local = FileSystem.getLocal(new Configuration());//建立一個本地的檔案系統物件

hdfs.copyFromLocalFile(new Path(localPath),new Path(hdfsPath));

2. hdfs 上建立檔案並直接給定檔案的內容

FSDateOutputStream out = hdfs.create(new Path(hdfsPath));

out.write(fileContent.getBytes());

out.close();

hdfs 的讀過程


讀過程語言Description :
  1. 客戶端或者使用者透過呼叫FileSystem 物件的 open 方法開啟需要讀取的檔案,這對 HDFS 來說是常見一個分散式檔案系統的一個讀取例項。
  2. FileSystem 透過遠端協議呼叫 NameNode 確定檔案的前幾個 Block 的位置。對於每一個 Block Namenode 返回含有那個Block  的“後設資料”,即檔案基本資訊;接下來, DataNode 按照上文定義的距離來進行排序,如果Client 本身就是一個 DataNode 優先從本地 DataNode 讀物資料。 HDFS 例項完成以上工作後,返回一個 FSDataInputStream 給客戶端,讓其從 FSDataInputStream 中讀取資料。 FSDataInputStream 接著包裝一個 DFSInputStream 用來管理 DataNode NameNode I/O
  3. NameNode 向客戶端返回一個包含資料資訊的地址,客戶端格努詆譭建立一個 FSDataInputStream 開始對資料進行讀取。
  4. FSDataInputStream 根據開始存放的前幾個 Blocks DataNode 的地址,連線到最近的 DataNode 上對資料開始從頭讀取。客戶端反覆呼叫 read() 方法,以流式方式從DataNode 讀取資料
  5. 當讀到Block 的結尾的時候, FSDataInputStream 會關閉當前 DataNode 的地址,然後查詢能夠讀取下一個Block 的最好的 DataNode 。這些操作對客戶端是透明的,客戶端感覺到的是連續的流,也就是說讀取的時候就開始查詢下一個塊所在的地址。
  6. 讀取完成呼叫close() 方法,關閉FSDataInputStream
Read  API :
1 . h dfs 上下載檔案到本地

Configuration hdfsConf = new Configuration();// 建立一個hdfs 的環境變數

String namenodeURI=”hdfs://hadoop001:8020”;//namenode的統一資源定位符

String username=”root”;// 訪問指定使用者的hdfs

FileSystem hdfs = FileSystem.get(new URI(namenodeURI),hdfsConf,username);// 建立一個hdfs 的檔案系統物件

FileSystem local = FileSystem.getLocal(new Configuration());//建立一個本地的檔案系統物件

hdfs.copyToLocalFile(new Path(hdfsPath),new Path(localPath));

3.  hdfs 上讀取給定檔案的內容

Path path = new Path(hdfsFilePath);//檔案路徑

FSDataInputStream in = hdfs.open(path);//獲取檔案輸入流

FileStatus status = hdfs.getFileStatus(path);//獲取檔案的後設資料資訊

//獲取檔案後設資料中的檔案大小

byte[] bytes = new byte[Integer.pareInt(String.valueOf(status.getLen()))];

//將輸入流中的全部內容一次性讀取出來

in.readFully(0,bytes);

System.out.println(new String(bytes));//將讀取的檔案列印輸出

in.close();

hdfs 的整體過程


來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/69913892/viewspace-2654618/,如需轉載,請註明出處,否則將追究法律責任。

相關文章