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
  • 在本篇教程中,我們學習瞭如何使用 Taurus.MVC WebMVC 框架創建一個簡單的頁面。 我們創建了一個控制器並編寫了一個用於呈現頁面的方法,然後創建了對應的視圖,並最終成功運行了應用程式。 在下一篇教程中,我們將繼續探索 Taurus.MVC WebMVC 框架的更多功能和用法。 ...
  • 一:背景 1. 講故事 很多.NET開發者在學習高級調試的時候,使用sos的命令輸出會發現這裡也看不懂那裡也看不懂,比如截圖中的這位朋友。 .NET高級調試屬於一個偏冷門的領域,國內可觀測的資料比較少,所以很多東西需要你自己去探究源代碼,然後用各種調試工具去驗證,相關源代碼如下: coreclr: ...
  • 我一直都以為c中除以2的n次方可以使用右移n位代替,然而在實際調試中發現並不都是這樣的。是在計算餘數是發現了異常 被除數:114325068 右移15計算結果:3488 除法取整計算結果:3489 右移操作計算餘數:33772 除法取整計算餘數:1005 顯然:這是不一樣的。 移位操作是一條cpu指 ...
  • 在上一篇文章中,我們介紹了ReentrantLock類的一些基本用法,今天我們重點來介紹一下ReentrantLock其它的常用方法,以便對ReentrantLock類的使用有更深入的理解。 ...
  • Excelize 是 Go 語言編寫的用於操作電子錶格辦公文檔的開源基礎庫,2024年2月26日,社區正式發佈了 2.8.1 版本,該版本包含了多項新增功能、錯誤修複和相容性提升優化。 ...
  • 雲採用框架(Cloud Adoption Framework,簡稱CAF)為企業上雲提供策略和技術的指導原則和最佳實踐,幫助企業上好雲、用好雲、管好雲,併成功實現業務目標。本雲採用框架是基於服務大量企業客戶的經驗總結,將企業雲採用分為四個階段,並詳細探討企業應在每個階段採取的業務和技術策略;同時,還 ...
  • 與TXT文本文件,PDF文件更加專業也更適合傳輸,常用於正式報告、簡歷、合同等場合。項目中如果有使用Java將TXT文本文件轉為PDF文件的需求,可以查看本文中介紹的免費實現方法。 免費Java PDF庫 本文介紹的方法需要用到Free Spire.PDF for Java,該免費庫支持多種操作、轉 ...
  • 指針和引用 當我們需要在程式中傳遞變數的地址時,可以使用指針或引用。它們都可以用來間接訪問變數,但它們之間有一些重要的區別。 指針是一個變數,它存儲另一個變數的地址。通過指針,我們可以訪問存儲在該地址中的變數。指針可以被重新分配,可以指向不同的變數,也可以為NULL。指針使用*運算符來訪問存儲在地址 ...
  • 即使再小再簡單的需求,作為研發開發完畢之後,我們可以直接上線麽?其實很多時候事故往往就是由於“不以為意”發生的。事故的發生往往也遵循“墨菲定律”,這就要求我們更要敬畏線上,再小的需求點都需要經過嚴格的測試驗證才能上線。 ...
  • 這裡給大家分享我在網上總結出來的一些知識,希望對大家有所幫助 一、是什麼 許可權是對特定資源的訪問許可,所謂許可權控制,也就是確保用戶只能訪問到被分配的資源 而前端許可權歸根結底是請求的發起權,請求的發起可能有下麵兩種形式觸發 頁面載入觸發 頁面上的按鈕點擊觸發 總的來說,所有的請求發起都觸發自前端路由或 ...