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、預覽地址:http://139.155.137.144:9012 2、qq群:801913255 一、前言 隨著網路的發展,企業對於信息系統數據的保密工作愈發重視,不同身份、角色對於數據的訪問許可權都應該大相徑庭。 列如 1、不同登錄人員對一個數據列表的可見度是不一樣的,如數據列、數據行、數據按鈕 ...
  • 前言 上一篇文章寫瞭如何使用RabbitMQ做個簡單的發送郵件項目,然後評論也是比較多,也是準備去學習一下如何確保RabbitMQ的消息可靠性,但是由於時間原因,先來說說設計模式中的簡單工廠模式吧! 在瞭解簡單工廠模式之前,我們要知道C#是一款面向對象的高級程式語言。它有3大特性,封裝、繼承、多態。 ...
  • Nodify學習 一:介紹與使用 - 可樂_加冰 - 博客園 (cnblogs.com) Nodify學習 二:添加節點 - 可樂_加冰 - 博客園 (cnblogs.com) 介紹 Nodify是一個WPF基於節點的編輯器控制項,其中包含一系列節點、連接和連接器組件,旨在簡化構建基於節點的工具的過程 ...
  • 創建一個webapi項目做測試使用。 創建新控制器,搭建一個基礎框架,包括獲取當天日期、wiki的請求地址等 創建一個Http請求幫助類以及方法,用於獲取指定URL的信息 使用http請求訪問指定url,先運行一下,看看返回的內容。內容如圖右邊所示,實際上是一個Json數據。我們主要解析 大事記 部 ...
  • 最近在不少自媒體上看到有關.NET與C#的資訊與評價,感覺大家對.NET與C#還是不太瞭解,尤其是對2016年6月發佈的跨平臺.NET Core 1.0,更是知之甚少。在考慮一番之後,還是決定寫點東西總結一下,也回顧一下.NET的發展歷史。 首先,你沒看錯,.NET是跨平臺的,可以在Windows、 ...
  • Nodify學習 一:介紹與使用 - 可樂_加冰 - 博客園 (cnblogs.com) Nodify學習 二:添加節點 - 可樂_加冰 - 博客園 (cnblogs.com) 添加節點(nodes) 通過上一篇我們已經創建好了編輯器實例現在我們為編輯器添加一個節點 添加model和viewmode ...
  • 前言 資料庫併發,數據審計和軟刪除一直是數據持久化方面的經典問題。早些時候,這些工作需要手寫複雜的SQL或者通過存儲過程和觸發器實現。手寫複雜SQL對軟體可維護性構成了相當大的挑戰,隨著SQL字數的變多,用到的嵌套和複雜語法增加,可讀性和可維護性的難度是幾何級暴漲。因此如何在實現功能的同時控制這些S ...
  • 類型檢查和轉換:當你需要檢查對象是否為特定類型,並且希望在同一時間內將其轉換為那個類型時,模式匹配提供了一種更簡潔的方式來完成這一任務,避免了使用傳統的as和is操作符後還需要進行額外的null檢查。 複雜條件邏輯:在處理複雜的條件邏輯時,特別是涉及到多個條件和類型的情況下,使用模式匹配可以使代碼更 ...
  • 在日常開發中,我們經常需要和文件打交道,特別是桌面開發,有時候就會需要載入大批量的文件,而且可能還會存在部分文件缺失的情況,那麼如何才能快速的判斷文件是否存在呢?如果處理不當的,且文件數量比較多的時候,可能會造成卡頓等情況,進而影響程式的使用體驗。今天就以一個簡單的小例子,簡述兩種不同的判斷文件是否... ...
  • 前言 資料庫併發,數據審計和軟刪除一直是數據持久化方面的經典問題。早些時候,這些工作需要手寫複雜的SQL或者通過存儲過程和觸發器實現。手寫複雜SQL對軟體可維護性構成了相當大的挑戰,隨著SQL字數的變多,用到的嵌套和複雜語法增加,可讀性和可維護性的難度是幾何級暴漲。因此如何在實現功能的同時控制這些S ...