04HDFS簡介

来源:https://www.cnblogs.com/touch-fish/archive/2023/01/28/17069835.html
-Advertisement-
Play Games

隨著業務的發展,系統會越來越龐大,原本簡單穩定的功能,可能在不斷迭代後複雜度上升,潛在的風險也隨之暴露,導致最終服務不穩定,造成業務價值的損失。而為了減少這種情況,其中一種比較好的方式就是提高代碼質量,比如通過代碼審查,從而降低錯誤風險,但是,代碼審查難度大,代碼缺陷、漏洞不易發現,且審查工作隨著代 ...


HDFS簡介

一、什麼是HDFS

HDFS全稱是Hadoop Distributed File System,簡稱HDFS。這是一個分散式文件系統,當數據規模大小超過一臺物理電腦的存儲能力時,就有必要進行分區並存儲到若幹台物理電腦上。管理網路中跨多台電腦的文件系統稱為分散式文件系統。

Hadoop的文件系統是一個抽象的概念,java的抽象類是org.apache.hadoop.fs.FileSystem,在創建一個FileSystem的時候,FileSystem使用文件系統URI的Schema作為查詢配置或者SPI尋找實現類(類似JDBC)。FileSystem有很多實現,HDFS只是其中的一個實現,它的實現類是org.apache.hadoop.hdfs.DistributedFileSystem,它的URI schema為hdfs。Hadoop預設配置的文件系統實現是org.apache.hadoop.fs.LocalFileSystem,URI schema為file,用於管理本地文件。


二、HDFS的基礎概念

1、數據塊

塊設備(例如硬碟)一般會有一個預設塊大小,這是設備讀寫的最小單位,這類設備的塊大小一般為幾千位元組。HDFS同樣有塊的概念,預設情況下HDFS的塊大小為128MB。但是與硬碟的文件系統不一樣,當文件小於HDFS的塊大小時,不會占用整個塊的空間,例如一個1MB大小的文件只占用了1MB的空間,而不是128MB。HDFS的塊比硬碟的大是為了最小化定址開銷,如果塊足夠大,從磁碟傳輸數據的時間會明顯大於定位這個塊位置需要的時間,所以傳輸一個大文件的時間取決於磁碟傳輸速率。

使用塊來管理分散式文件系統有很多好處,例如一個文件可以大於某個物理設備的容量,文件並不需要存儲在一個物理設備上。另一個好處是塊可以存儲在多個節點上,防止某個設備因為故障而丟失數據。

2、namenode和datanode

HDFS集群有兩種節點,分別是namenode和datanode。以管理節點——工作節點方式對外提供服務,即client連接namenode,一個namenode節點負責管理多個datanode。

namenode負責管理文件系統的命名空間,它維護文件系統元數據信息,例如目錄和文件名稱。這些信息以文件的形式永久保存在硬碟上:分別是命令空間鏡像文件和編輯日誌文件。namenode也記錄每個文件的塊所在的數據節點信息,但它並不永久保存塊的位置,這些信息會在啟動的時候根據數據節點的數據重建。

datanode就是文件系統的工作節點。它們根據需要存儲數據塊信息,並且定期向namenode發送所存儲的塊列表。HDFS通過把數據塊冗餘到多個datanode實現數據的安全性,預設副本數量為3。

namenode對外提供服務的時候需要把所有的文件元數據載入到記憶體,重啟的時候會利用鏡像文件和編輯日誌重建數據,鏡像文件類似於Redis的rdb文件。namenode會周期性歸檔編輯日誌來生成一個更加新的鏡像文件,由於歸檔編輯日誌的時候namenode也會對外提供服務,這段時間的操作會寫入到編輯日誌中,所以namenode需要鏡像文件和編輯日誌一起重建文件元數據。一個大規模的HDFS的恢復是非常消耗時間的(取決於所管理的數據規模),由於namenode是管理節點,沒有namenode整個文件系統將無法使用,所以相對datanode,namenode的高可用非常重要。本節主要為對HDFS簡單介紹,故先不討論HDFS的高可用方案。

3、聯邦HDFS

由於namenode在記憶體中維護系統內文件和數據塊的關係,很明顯namenode運行機器的記憶體會限制整個集群能存儲的文件數量。Hadoop在2.x版本引入的聯邦namenode,在聯邦環境下,每個namenode管理一個命名空間的一部分。例如一個namenode管理/a目錄下的所有文件,另一個namenode管理/b目錄下的所有文件。在聯邦環境下,每個namenode是獨立的,其中一個namenode失效了也不會影響其他namenode。


三、hadoop命令行

Hadoop命令行的fs參數提供了一些方便訪問文件系統的操作,所有的參數和格式可以在官網文檔FileSystemShell中查詢到,這裡簡單列舉一些常用的操作。

-cat:讀取文件,並且輸出到標準輸出

格式:hadoop fs -cat [-ignoreCrc] URI [URI ...]

例如:

  • 列印本地文件系統下的text.txt內容

    hadoop fs -cat file:///D:/test.txt
    
  • 列印hdfs上根目錄下的a.txt內容

    hadoop fs -cat hdfs://192.168.73.130:8082/a.txt
    

-ls:列出路徑下的文件內容

格式:hadoop fs -ls URI

例如:

  • 列出hdfs上根目錄的文件內容

    hadoop fs -ls hdfs://192.168.73.130:8082/
    

輸出每一列含義為:許可權,副本數,所屬用戶,所屬用戶組,文件大小,修改時間,文件名。許可權欄位由有7個標識位,第一個標識位含義是文件類型,如果是目錄則為d,然後緊跟的6個標識位表示所屬用戶、所屬用戶組、其他用戶的是否可讀、可寫、可執行,可執行許可權可以忽略,因為不能在HDFS中執行。第二列為副本數,目錄的元數據保存在namenode上,所以沒有副本數。

示例輸入如下:

hadoop fs -ls hdfs://192.168.73.130:8082/
Found 2 items
-rw-r--r--   3 debian supergroup  19481 2023-01-25 15:30 hdfs://192.168.73.130:8082/a.txt
drwxr-xr-x   - debian supergroup      0 2023-01-28 09:08 hdfs://192.168.73.130:8082/test

-copyFromLocal:複製本地文件到HDFS

格式:hadoop fs -copyFromLocal localsrc URI

例如:

  • 把本地的文件a.txt複製到HDFS的/testDir/a.txt上

    hadoop fs -copyFromLocal a.txt hdfs://192.168.73.130:8082/testDir/a.txt
    

-copyToLocal:複製HDFS文件到本地

格式:hadoop fs -copyToLocal URI localsrc

例如:

  • 把HDFS的/testDir/a.txt複製到本地

    hadoop fs -copyToLocal hdfs://localhost:8082/testDir/a.txt a.txt
    

四、FileSystem常用api

1、文件的讀取

使用方法FileSystem#open()可以打開一個FSDataInputStream輸入流,然後可以像讀取本地文件一樣文件中的數據。但是與一般的輸入流不一樣,FSDataInputStream實現了Seekable和介面PositionedReadable,它們分別支持隨機讀取和指定位置讀取。

Seekable的聲明如下:

public interface Seekable {
  /**
   * 設置下一次讀取的時,使用的偏移量
   */
  void seek(long pos) throws IOException;
  
  /**
   * 返回當前讀取偏移量
   */
  long getPos() throws IOException;
}

getPos返回當前讀取偏移量,seek設置下一次read的偏移量,偏移量是當前距離文件起始位置的位元組數。例如可以用如下代碼重覆讀取文件開頭的2048個位元組;

FSDataInputStream in = .....;
byte[] buff = new buff[2048];
in.read(buff);
in.seek(0);
in.read(buff);

seek使用起來很方便,但是是一個相對高開銷的操作,需要慎重使用。

PositionedReadable的聲明如下:

public interface PositionedReadable {
  /**
   * 從position指定的位置開始讀取length個長度的數據,複製到buffer的offset處,返回實際讀取到的位元組數
   */
  int read(long position, byte[] buffer, int offset, int length)
    throws IOException;
  
  /**
   * 從position指定的位置開始讀取length個長度的數據,複製到buffer的offset處
   * 如果到達文件結尾拋出EOFException
   */
  void readFully(long position, byte[] buffer, int offset, int length) throws IOException;
  
   /**
   * 從position指定的位置開始讀取buffer.length個長度的數據,複製到buffer的offset處
   * 如果到達文件結尾拋出EOFException
   */
  void readFully(long position, byte[] buffer) throws IOException;
}

read函數把指定偏移量數據讀取到buffer中,但是實際讀取的位元組數需要調用者接受返回值進行判斷。readFully效果也類似,但是如果到達文件結尾會拋出EOFException。PositionedReadable所有的方法都不會改變當前流讀取文件的位置,同時它的方法也都是線程安全的。

2、文件的寫入

傳入一個Path對象,然後使用FileSystem#create可以創建一個新文件,並且返回一個FSDataOutputStream對象。與java其他的api不一樣,調用create方法會自動創建父級目錄。

使用FileSystem#append()可以向一個已存在的文件尾追加內容,需要說明的是這個方法是一個可選的實現,並不是每一個文件系統都正常此方法。

3、目錄創建

調用FileSystem#mkdirs()方法可以新建一個目錄,通常創建文件不需要顯示調用此方法,因為創建文件會自動創建對應的父級目錄。

4、文件的刪除

調用FileSystem#delete()可以刪除一個文件或者目錄。

5、文件元數據信息

使用FileSystem#getFileStatus方法可以返回一個FileStatus對象來獲取文件或者目錄的的狀態信息,例如是否為目錄、許可權、文件長度等數據。

FileSystem#listStatus可以列出目錄下所有的文件信息。listStatus有多個重載方法,可以額外傳入一個org.apache.hadoop.fs.PathFilter用來過濾目錄的文件。

6、HDFS的一致性模型

對於創建一個目錄,HDFS可以保證操作是立即可見的。但是對於寫入數據並不能保證其可見性。例如對於以下一段Java程式代碼:

OutputStream out = ...;
out.write(buff);
out.flush();

如果是操作本地文件,調用flush方法,會把緩衝區數據刷新到硬碟上,保證其可見性。然而對於HDFS,即使調用了flush方法也不能保證可見性,需要等到數據超過一個塊之後才能對其他讀取進程可見。但是HDFS的實現提供了兩個方法用於保證可見性,分別是FSDataOutputStream#hflushFSDataOutputStream#hsynchsync和操作系統的sync方法類似,保證數據已經存儲在datanode的硬碟上,而hflush僅僅保證數據寫入到datanode的記憶體。調用close關閉流會自動調用一次hflush


五、demo程式

我使用FileSystem常用api實現了一個客戶端demo,代碼地址在github 的hdfsApiExample模塊,打包此模塊可以得到一個hdfs-api-example-1.0-SNAPSHOT.jar的文件,它的使用方法如下:

參數:

  • fs:指定hdfs的namenode地址,假設你有一個namenode地址是hdfs://192.168.73.130:8082
  • u:操作hdfs的用戶,根據hdfs配置情況,寫入的時候可能需要這個參數
  • o:實際需要執行的命令,分別支持ls(查詢目錄文件),rm(刪除),mkdir(創建目錄),cp(複製文件)

示例:

  • 列出hdfs上,根目錄的文件

    hadoop jar hdfs-api-example-1.0-SNAPSHOT.jar -fs hdfs://192.168.73.130:8082 -u debian -o ls /
    
  • 刪除hdfs上,/cnblog目錄。使用額外的r參數遞歸刪除非空目錄

    hadoop jar hdfs-api-example-1.0-SNAPSHOT.jar -fs hdfs://192.168.73.130:8082 -u debian -o rm r /cnblog
    
  • 在根目錄下創建一個cnblog目錄

    hadoop jar hdfs-api-example-1.0-SNAPSHOT.jar -fs hdfs://192.168.73.130:8082 -u debian -o mkdir /cnblog
    
  • 複製本地文件test.txt到hdfs的根目錄上

    hadoop jar hdfs-api-example-1.0-SNAPSHOT.jar -fs hdfs://192.168.73.130:8082 -u debian -o cp text.txt hdfs:/test.text
    
  • 複製hdfs的根目錄文件text.txt到本地目錄上

    hadoop jar hdfs-api-example-1.0-SNAPSHOT.jar -fs hdfs://192.168.73.130:8082 -u debian -o cp hdfs:/test.text text.txt
    

您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • *以下內容為本人的學習筆記,如需要轉載,請聲明原文鏈接 微信公眾號「englyf」https://mp.weixin.qq.com/s/2GFLTstDC7w6u3fTJxflNA 本文大概 1685 個字,閱讀需花 6 分鐘內容不多, 但也花了一些精力如要交流, 歡迎關註我然後評論區留言 謝謝你的 ...
  • 題目描述 運行 C 程式,輸出 100 至 200 之間的質數。 輸入描述 無 輸出描述 輸出 100 至 200 之間的質數,每行輸出一個質數,每個質數前面需要帶有序號。 輸出樣例 解題思路 在《一文解決如何使用 C 語言判斷質數(素數)》一文中,我詳細講解了質數以及如何使用 C 語言判斷質數,本 ...
  • 實現Spring底層機制-02 3.實現任務階段1 3.1知識拓展-類載入器 Java的類載入器有三種: Bootstrap類載入器 對應路徑 jre/lib Ext類載入器 對應路徑 jre/lib/ext App類載入器 對應路徑 classpath classpath 類路徑,就是java.e ...
  • 這篇文章主要討論在RPC框架下如何優雅關閉和啟動服務,包括服務提供方如何通知調用方服務關閉重啟信息,服務提供方如何在關閉後處理現有請求和心情求;服務啟動時,如何實現啟動預熱和延遲暴露。 ...
  • Collection常用方法彙總 Collection公共的方法 Collection是單列結合的祖宗介面,它的方法是所有單列集合都可以繼承使用的。 //把給定元素添加到集合中 public boolean add(E e) //把給定元素從集合中刪除 public boolean remove(E ...
  • 談談你對 Java 平臺的理解?“Java 是解釋執行”,這句話正確嗎? Java 本身是一種面向對象的語言,最顯著的特性有兩個方面,一是所謂的“一處編譯,處處運行”(Write once,run anywhere),能夠非常容易地獲得跨平臺能力;另外就是垃圾收集(GC,Garbage Collec ...
  • 首先我們來嘗試將分片的圖片複原為正常的圖片 這裡是六張切成小細條的圖片,原本是一張大圖的,現在我們用python將他們合併到一塊,題外話圖片來源於中華連環畫,*http://www.zhlhh.com/* 這個網站內有很多優秀的連環畫,而且大部分都是免費,推薦給大家 我的思路是用matlib讀圖片, ...
  • IoC 反轉控制原則也被叫做依賴註入 DI, 容器按照配置註入實例化的對象. 本文將實現一個輕量化的 IoC 容器, 完成對象的實例化和註入, 基於註解不依賴於任何庫. (註解參考 JSR-330) ...
一周排行
    -Advertisement-
    Play Games
  • 1. 說明 /* Performs operations on System.String instances that contain file or directory path information. These operations are performed in a cross-pla ...
  • 視頻地址:【WebApi+Vue3從0到1搭建《許可權管理系統》系列視頻:搭建JWT系統鑒權-嗶哩嗶哩】 https://b23.tv/R6cOcDO qq群:801913255 一、在appsettings.json中設置鑒權屬性 /*jwt鑒權*/ "JwtSetting": { "Issuer" ...
  • 引言 集成測試可在包含應用支持基礎結構(如資料庫、文件系統和網路)的級別上確保應用組件功能正常。 ASP.NET Core 通過將單元測試框架與測試 Web 主機和記憶體中測試伺服器結合使用來支持集成測試。 簡介 集成測試與單元測試相比,能夠在更廣泛的級別上評估應用的組件,確認多個組件一起工作以生成預 ...
  • 在.NET Emit編程中,我們探討了運算操作指令的重要性和應用。這些指令包括各種數學運算、位操作和比較操作,能夠在動態生成的代碼中實現對數據的處理和操作。通過這些指令,開發人員可以靈活地進行算術運算、邏輯運算和比較操作,從而實現各種複雜的演算法和邏輯......本篇之後,將進入第七部分:實戰項目 ...
  • 前言 多表頭表格是一個常見的業務需求,然而WPF中卻沒有預設實現這個功能,得益於WPF強大的控制項模板設計,我們可以通過修改控制項模板的方式自己實現它。 一、需求分析 下圖為一個典型的統計表格,統計1-12月的數據。 此時我們有一個需求,需要將月份按季度劃分,以便能夠直觀地看到季度統計數據,以下為該需求 ...
  • 如何將 ASP.NET Core MVC 項目的視圖分離到另一個項目 在當下這個年代 SPA 已是主流,人們早已忘記了 MVC 以及 Razor 的故事。但是在某些場景下 SSR 還是有意想不到效果。比如某些靜態頁面,比如追求首屏載入速度的時候。最近在項目中回歸傳統效果還是不錯。 有的時候我們希望將 ...
  • System.AggregateException: 發生一個或多個錯誤。 > Microsoft.WebTools.Shared.Exceptions.WebToolsException: 生成失敗。檢查輸出視窗瞭解更多詳細信息。 內部異常堆棧跟蹤的結尾 > (內部異常 #0) Microsoft ...
  • 引言 在上一章節我們實戰了在Asp.Net Core中的項目實戰,這一章節講解一下如何測試Asp.Net Core的中間件。 TestServer 還記得我們在集成測試中提供的TestServer嗎? TestServer 是由 Microsoft.AspNetCore.TestHost 包提供的。 ...
  • 在發現結果為真的WHEN子句時,CASE表達式的真假值判斷會終止,剩餘的WHEN子句會被忽略: CASE WHEN col_1 IN ('a', 'b') THEN '第一' WHEN col_1 IN ('a') THEN '第二' ELSE '其他' END 註意: 統一各分支返回的數據類型. ...
  • 在C#編程世界中,語法的精妙之處往往體現在那些看似微小卻極具影響力的符號與結構之中。其中,“_ =” 這一組合突然出現還真不知道什麼意思。本文將深入剖析“_ =” 的含義、工作原理及其在實際編程中的廣泛應用,揭示其作為C#語法奇兵的重要角色。 一、下劃線 _:神秘的棄元符號 下劃線 _ 在C#中並非 ...