日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

HDFS初探之旅

發(fā)布時間:2025/6/15 编程问答 23 豆豆
生活随笔 收集整理的這篇文章主要介紹了 HDFS初探之旅 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

  HDFS(Hadoop Distributed File System)是Hadoop項目的核心子項目,是分布式計算中數(shù)據(jù)存儲管理的基礎(chǔ),是基于流數(shù)據(jù)模式訪問和處理超大文件的需求而開發(fā)的,可以運行于廉價的商用服務(wù)器上。它所具有的高容錯、高可靠性、高可擴展性、高獲得性、高吞吐率等特征為海量數(shù)據(jù)提供了不怕故障的存儲,為超大數(shù)據(jù)集(Large Data Set)的應(yīng)用處理帶來了很多便利。

  Hadoop整合了眾多文件系統(tǒng),在其中有一個綜合性的文件系統(tǒng)抽象,它提供了文件系統(tǒng)實現(xiàn)的各類接口,HDFS只是這個抽象文件系統(tǒng)的一個實例。提供了一個高層的文件系統(tǒng)抽象類org.apache.hadoop.fs.FileSystem,這個抽象類展示了一個分布式文件系統(tǒng),并有幾個具體實現(xiàn),如下表1-1所示。

表1-1 Hadoop的文件系統(tǒng)

文件系統(tǒng)

URI方案

Java實現(xiàn)

org.apache.hadoop

定義

Local

file

fs.LocalFileSystem

支持有客戶端校驗和本地文件系統(tǒng)。帶有校驗和的本地系統(tǒng)文件在fs.RawLocalFileSystem中實現(xiàn)。

HDFS

hdfs

hdfs.DistributionFileSystem

Hadoop的分布式文件系統(tǒng)。

HFTP

hftp

hdfs.HftpFileSystem

支持通過HTTP方式以只讀的方式訪問HDFSdistcp經(jīng)常用在不同HDFS集群間復制數(shù)據(jù)。

HSFTP

hsftp

hdfs.HsftpFileSystem

支持通過HTTPS方式以只讀的方式訪問HDFS

HAR

har

fs.HarFileSystem

構(gòu)建在Hadoop文件系統(tǒng)之上,對文件進行歸檔。Hadoop歸檔文件主要用來減少NameNode內(nèi)存使用

KFS

kfs

fs.kfs.KosmosFileSystem

Cloudstore(其前身是Kosmos文件系統(tǒng))文件系統(tǒng)是類似于HDFSGoogleGFS文件系統(tǒng),使用C++編寫。

FTP

ftp

fs.ftp.FtpFileSystem

FTP服務(wù)器支持的文件系統(tǒng)。

S3(本地)

s3n

fs.s3native.NativeS3FileSystem

基于Amazon S3的文件系統(tǒng)。

S3(基于塊)

s3?

fs.s3.NativeS3FileSystem

基于Amazon S3的文件系統(tǒng),以塊格式存儲解決了S35GB文件大小的限制。

  Hadoop提供了許多文件系統(tǒng)的接口,用戶可以使用URI方案選取合適的文件系統(tǒng)來實現(xiàn)交互。

2、HDFS基礎(chǔ)概念

2.1 數(shù)據(jù)塊(block)

  • HDFS(Hadoop Distributed File System)默認的最基本的存儲單位是64M的數(shù)據(jù)塊。
  • 和普通文件系統(tǒng)相同的是,HDFS中的文件是被分成64M一塊的數(shù)據(jù)塊存儲的。
  • 不同于普通文件系統(tǒng)的是,HDFS中,如果一個文件小于一個數(shù)據(jù)塊的大小,并不占用整個數(shù)據(jù)塊存儲空間。

2.2 NameNode和DataNode

  HDFS體系結(jié)構(gòu)中有兩類節(jié)點,一類是NameNode,又叫"元數(shù)據(jù)節(jié)點";另一類是DataNode,又叫"數(shù)據(jù)節(jié)點"。這兩類節(jié)點分別承擔Master和Worker具體任務(wù)的執(zhí)行節(jié)點。

  1)元數(shù)據(jù)節(jié)點用來管理文件系統(tǒng)的命名空間

  • 其將所有的文件和文件夾的元數(shù)據(jù)保存在一個文件系統(tǒng)樹中。
  • 這些信息也會在硬盤上保存成以下文件:命名空間鏡像(namespace image)及修改日志(edit log)
  • 其還保存了一個文件包括哪些數(shù)據(jù)塊,分布在哪些數(shù)據(jù)節(jié)點上。然而這些信息并不存儲在硬盤上,而是在系統(tǒng)啟動的時候從數(shù)據(jù)節(jié)點收集而成的。

  2)數(shù)據(jù)節(jié)點是文件系統(tǒng)中真正存儲數(shù)據(jù)的地方。

  • 客戶端(client)或者元數(shù)據(jù)信息(namenode)可以向數(shù)據(jù)節(jié)點請求寫入或者讀出數(shù)據(jù)塊。
  • 其周期性的向元數(shù)據(jù)節(jié)點回報其存儲的數(shù)據(jù)塊信息。

  3)從元數(shù)據(jù)節(jié)點(secondary namenode)

  • 從元數(shù)據(jù)節(jié)點并不是元數(shù)據(jù)節(jié)點出現(xiàn)問題時候的備用節(jié)點,它和元數(shù)據(jù)節(jié)點負責不同的事情。
  • 其主要功能就是周期性將元數(shù)據(jù)節(jié)點的命名空間鏡像文件和修改日志合并,以防日志文件過大。這點在下面會相信敘述。
  • 合并過后的命名空間鏡像文件也在從元數(shù)據(jù)節(jié)點保存了一份,以防元數(shù)據(jù)節(jié)點失敗的時候,可以恢復。

2.3 元數(shù)據(jù)節(jié)點目錄結(jié)構(gòu)

?

  

?

  VERSION文件是java properties文件,保存了HDFS的版本號。

  • layoutVersion是一個負整數(shù),保存了HDFS的持續(xù)化在硬盤上的數(shù)據(jù)結(jié)構(gòu)的格式版本號。
  • namespaceID是文件系統(tǒng)的唯一標識符,是在文件系統(tǒng)初次格式化時生成的。
  • cTime此處為0
  • storageType表示此文件夾中保存的是元數(shù)據(jù)節(jié)點的數(shù)據(jù)結(jié)構(gòu)。

?

namespaceID=1232737062

cTime=0

storageType=NAME_NODE

layoutVersion=-18

?

2.4 數(shù)據(jù)節(jié)點的目錄結(jié)構(gòu)

?

  

  • 數(shù)據(jù)節(jié)點的VERSION文件格式如下:

?

namespaceID=1232737062

storageID=DS-1640411682-127.0.1.1-50010-1254997319480

cTime=0

storageType=DATA_NODE

layoutVersion=-18

?

  • blk_<id>保存的是HDFS的數(shù)據(jù)塊,其中保存了具體的二進制數(shù)據(jù)。
  • blk_<id>.meta保存的是數(shù)據(jù)塊的屬性信息:版本信息,類型信息,和checksum
  • 當一個目錄中的數(shù)據(jù)塊到達一定數(shù)量的時候,則創(chuàng)建子文件夾來保存數(shù)據(jù)塊及數(shù)據(jù)塊屬性信息。

2.5 文件系統(tǒng)命名空間映像文件及修改日志

  • 當文件系統(tǒng)客戶端(client)進行寫操作時,首先把它記錄在修改日志中(edit log)
  • 元數(shù)據(jù)節(jié)點在內(nèi)存中保存了文件系統(tǒng)的元數(shù)據(jù)信息。在記錄了修改日志后,元數(shù)據(jù)節(jié)點則修改內(nèi)存中的數(shù)據(jù)結(jié)構(gòu)。
  • 每次的寫操作成功之前,修改日志都會同步(sync)到文件系統(tǒng)。
  • fsimage文件,也即命名空間映像文件,是內(nèi)存中的元數(shù)據(jù)在硬盤上的checkpoint,它是一種序列化的格式,并不能夠在硬盤上直接修改。
  • 同數(shù)據(jù)的機制相似,當元數(shù)據(jù)節(jié)點失敗時,則最新checkpoint的元數(shù)據(jù)信息從fsimage加載到內(nèi)存中,然后逐一重新執(zhí)行修改日志中的操作。
  • 從元數(shù)據(jù)節(jié)點就是用來幫助元數(shù)據(jù)節(jié)點將內(nèi)存中的元數(shù)據(jù)信息checkpoint到硬盤上的
  • checkpoint的過程如下:
    • 從元數(shù)據(jù)節(jié)點通知元數(shù)據(jù)節(jié)點生成新的日志文件,以后的日志都寫到新的日志文件中。
    • 從元數(shù)據(jù)節(jié)點用http get從元數(shù)據(jù)節(jié)點獲得fsimage文件及舊的日志文件。
    • 從元數(shù)據(jù)節(jié)點將fsimage文件加載到內(nèi)存中,并執(zhí)行日志文件中的操作,然后生成新的fsimage文件。
    • 從元數(shù)據(jù)節(jié)點獎新的fsimage文件用http post傳回元數(shù)據(jù)節(jié)點
    • 元數(shù)據(jù)節(jié)點可以將舊的fsimage文件及舊的日志文件,換為新的fsimage文件和新的日志文件(第一步生成的),然后更新fstime文件,寫入此次checkpoint的時間。
    • 這樣元數(shù)據(jù)節(jié)點中的fsimage文件保存了最新的checkpoint的元數(shù)據(jù)信息,日志文件也重新開始,不會變的很大了。

?

?

3、HDFS體系結(jié)構(gòu)

  HDFS是一個主/從(Mater/Slave)體系結(jié)構(gòu),從最終用戶的角度來看,它就像傳統(tǒng)的文件系統(tǒng)一樣,可以通過目錄路徑對文件執(zhí)行CRUD(Create、Read、Update和Delete)操作。但由于分布式存儲的性質(zhì),HDFS集群擁有一個NameNode和一些DataNode。NameNode管理文件系統(tǒng)的元數(shù)據(jù),DataNode存儲實際的數(shù)據(jù)。客戶端通過同NameNode和DataNodes的交互訪問文件系統(tǒng)。客戶端聯(lián)系NameNode以獲取文件的元數(shù)據(jù),而真正的文件I/O操作是直接和DataNode進行交互的。

?

圖3.1 HDFS總體結(jié)構(gòu)示意圖

?

  1)NameNode、DataNode和Client

  • NameNode可以看作是分布式文件系統(tǒng)中的管理者,主要負責管理文件系統(tǒng)的命名空間、集群配置信息和存儲塊的復制等。NameNode會將文件系統(tǒng)的Meta-data存儲在內(nèi)存中,這些信息主要包括了文件信息、每一個文件對應(yīng)的文件塊的信息和每一個文件塊在DataNode的信息等。
  • DataNode是文件存儲的基本單元,它將Block存儲在本地文件系統(tǒng)中,保存了Block的Meta-data,同時周期性地將所有存在的Block信息發(fā)送給NameNode。
  • Client就是需要獲取分布式文件系統(tǒng)文件的應(yīng)用程序。

  2)文件寫入

  • Client向NameNode發(fā)起文件寫入的請求。
  • NameNode根據(jù)文件大小和文件塊配置情況,返回給Client它所管理部分DataNode的信息。
  • Client將文件劃分為多個Block,根據(jù)DataNode的地址信息,按順序?qū)懭氲矫恳粋€DataNode塊中。

  3)文件讀取

  • Client向NameNode發(fā)起文件讀取的請求。
  • NameNode返回文件存儲的DataNode的信息。
  • Client讀取文件信息。

?

  HDFS典型的部署是在一個專門的機器上運行NameNode,集群中的其他機器各運行一個DataNode;也可以在運行NameNode的機器上同時運行DataNode,或者一臺機器上運行多個DataNode。一個集群只有一個NameNode的設(shè)計大大簡化了系統(tǒng)架構(gòu)。

4、HDFS的優(yōu)缺點

4.1 HDFS的優(yōu)點

  1)處理超大文件

  這里的超大文件通常是指百MB、設(shè)置數(shù)百TB大小的文件。目前在實際應(yīng)用中,HDFS已經(jīng)能用來存儲管理PB級的數(shù)據(jù)了。

  2)流式的訪問數(shù)據(jù)

  HDFS的設(shè)計建立在更多地響應(yīng)"一次寫入、多次讀寫"任務(wù)的基礎(chǔ)上。這意味著一個數(shù)據(jù)集一旦由數(shù)據(jù)源生成,就會被復制分發(fā)到不同的存儲節(jié)點中,然后響應(yīng)各種各樣的數(shù)據(jù)分析任務(wù)請求。在多數(shù)情況下,分析任務(wù)都會涉及數(shù)據(jù)集中的大部分數(shù)據(jù),也就是說,對HDFS來說,請求讀取整個數(shù)據(jù)集要比讀取一條記錄更加高效

  3)運行于廉價的商用機器集群上

  Hadoop設(shè)計對硬件需求比較,只須運行在低廉的商用硬件集群上,而無需昂貴的高可用性機器上。廉價的商用機也就意味著大型集群中出現(xiàn)節(jié)點故障情況的概率非常高。這就要求設(shè)計HDFS時要充分考慮數(shù)據(jù)的可靠性,安全性及高可用性。

4.2 HDFS的缺點

  1)不適合低延遲數(shù)據(jù)訪問

  如果要處理一些用戶要求時間比較短的低延遲應(yīng)用請求,則HDFS不適合。HDFS是為了處理大型數(shù)據(jù)集分析任務(wù)的,主要是為達到數(shù)據(jù)吞吐量而設(shè)計的,這就可能要求以高延遲作為代價。

  改進策略:對于那些有低延時要求的應(yīng)用程序,HBase是一個更好的選擇。通過上層數(shù)據(jù)管理項目來盡可能地彌補這個不足。在性能上有了很大的提升,它的口號就是goes real time。使用緩存或多master設(shè)計可以降低client的數(shù)據(jù)請求壓力,以減少延時。還有就是對HDFS系統(tǒng)內(nèi)部的修改,這就得權(quán)衡大吞吐量與低延時了,HDFS不是萬能的銀彈。

  2)無法高效存儲大量小文件

  因為Namenode把文件系統(tǒng)的元數(shù)據(jù)放置在內(nèi)存中,所以文件系統(tǒng)所能容納的文件數(shù)目是由Namenode的內(nèi)存大小來決定。一般來說,每一個文件文件夾Block需要占據(jù)150字節(jié)左右的空間,所以,如果你有100萬個文件,每一個占據(jù)一個Block,你就至少需要300MB內(nèi)存。當前來說,數(shù)百萬的文件還是可行的,當擴展到數(shù)十億時,對于當前的硬件水平來說就沒法實現(xiàn)了。還有一個問題就是,因為Map task的數(shù)量是由splits來決定的,所以用MR處理大量的小文件時,就會產(chǎn)生過多的Maptask,線程管理開銷將會增加作業(yè)時間。舉個例子,處理10000M的文件,若每個split為1M,那就會有10000個Maptasks,會有很大的線程開銷;若每個split為100M,則只有100個Maptasks,每個Maptask將會有更多的事情做,而線程的管理開銷也將減小很多。

  改進策略:要想讓HDFS能處理好小文件,有不少方法。

  • 利用SequenceFile、MapFile、Har等方式歸檔小文件,這個方法的原理就是把小文件歸檔起來管理,HBase就是基于此的。對于這種方法,如果想找回原來的小文件內(nèi)容,那就必須得知道與歸檔文件的映射關(guān)系。
  • 橫向擴展,一個Hadoop集群能管理的小文件有限,那就把幾個Hadoop集群拖在一個虛擬服務(wù)器后面,形成一個大的Hadoop集群。google也是這么干過的。
  • 多Master設(shè)計,這個作用顯而易見了。正在研發(fā)中的GFS II也要改為分布式多Master設(shè)計,還支持Master的Failover,而且Block大小改為1M,有意要調(diào)優(yōu)處理小文件啊。
  • 附帶個Alibaba DFS的設(shè)計,也是多Master設(shè)計,它把Metadata的映射存儲和管理分開了,由多個Metadata存儲節(jié)點和一個查詢Master節(jié)點組成。

  3)不支持多用戶寫入及任意修改文件

  在HDFS的一個文件中只有一個寫入者,而且寫操作只能在文件末尾完成,即只能執(zhí)行追加操作。目前HDFS還不支持多個用戶同一文件操作,以及在文件任意位置進行修改。

5、HDFS常用操作

  先說一下"hadoop fs?和hadoop dfs的區(qū)別",看兩本Hadoop書上各有用到,但效果一樣,求證與網(wǎng)絡(luò)發(fā)現(xiàn)下面一解釋比較中肯。

  粗略的講,fs是個比較抽象的層面,在分布式環(huán)境中,fs就是dfs,但在本地環(huán)境中,fs是local file system,這個時候dfs就不能用。

5.1 文件操作

  1)列出HDFS文件

  此處為你展示如何通過"-ls"命令列出HDFS下的文件:

?

hadoop fs -ls

?

  執(zhí)行結(jié)果如圖5-1-1所示。在這里需要注意:在HDFS中未帶參數(shù)的"-ls"命名沒有返回任何值,它默認返回HDFS的"home"目錄下的內(nèi)容。在HDFS中,當前目錄這樣一個概念,也cd這個命令。

?

  

圖5-1-1 列出HDFS文件

  2)列出HDFS目錄下某個文檔中的文件

  此處為你展示如何通過"-ls 文件名"命令瀏覽HDFS下名為"input"的文檔中文件:

?

hadoop fs –ls input

?

  執(zhí)行結(jié)果如圖5-1-2所示。

?

  

圖5-1-2 列出HDFS下名為input的文檔下的文件

  3)上傳文件到HDFS

  此處為你展示如何通過"-put 文件1 文件2"命令將"Master.Hadoop"機器下的"/home/hadoop"目錄下的file文件上傳到HDFS上并重命名test

?

hadoop fs –put ~/file test

?

  執(zhí)行結(jié)果如圖5-1-3所示。在執(zhí)行"-put"時兩種可能,即是執(zhí)行成功執(zhí)行失敗。在上傳文件時,文件首先復制到DataNode上。只有所有的DataNode都成功接收完數(shù)據(jù),文件上傳才是成功的。其他情況(如文件上傳終端等)對HDFS來說都是做了無用功。

?

  

圖5-1-3 成功上傳file到HDFS

  4)將HDFS中文件復制本地系統(tǒng)

  此處為你展示如何通過"-get 文件1 文件2"命令將HDFS中的"output"文件復制到本地系統(tǒng)并命名為"getout"。

?

hadoop fs –get output getout

?

  執(zhí)行結(jié)果如圖5-1-4所示。

?

  

圖5-1-4 成功將HDFS中output文件復制到本地系統(tǒng)

  備注:與"-put"命令一樣,"-get"操作既可以操作文件,也可以操作目錄

  5)刪除HDFS下的文檔

  此處為你展示如何通過"-rmr 文件"命令刪除HDFS下名為"newoutput"的文檔:

?

hadoop fs –rmr newoutput

?

  執(zhí)行結(jié)果如圖5-1-5所示。

?

  

圖5-1-5 成功刪除HDFS下的newoutput文檔

  6)查看HDFS下某個文件

  此處為你展示如何通過"-cat 文件"命令查看HDFS下input文件中內(nèi)容:

?

hadoop fs -cat input/*

?

  執(zhí)行結(jié)果如圖5-1-6所示。

?

  

圖5-1-6 HDFS下input文件的內(nèi)容

  "hadoop fs"的命令遠不止這些,本小節(jié)介紹的命令已可以在HDFS上完成大多數(shù)常規(guī)操作。對于其他操作,可以通過"-help commandName"命令所列出的清單來進一步學習與探索。

5.2 管理與更新

  1)報告HDFS的基本統(tǒng)計情況

  此處為你展示通過"-report"命令如何查看HDFS的基本統(tǒng)計信息:

?

hadoop dfsadmin -report

?

  執(zhí)行結(jié)果如圖5-2-1所示。

?

  

圖5-2-1 HDFS基本統(tǒng)計信息

  2)退出安全模式

  NameNode在啟動時自動進入安全模式。安全模式是NameNode的一種狀態(tài),在這個階段,文件系統(tǒng)不允許有任何修改。安全模式的目的是在系統(tǒng)啟動時檢查各個DataNode上數(shù)據(jù)塊的有效性,同時根據(jù)策略對數(shù)據(jù)塊進行必要的復制刪除,當數(shù)據(jù)塊最小百分比數(shù)滿足的最小副本數(shù)條件時,會自動退出安全模式。

  系統(tǒng)顯示"Name node is in safe mode",說明系統(tǒng)正處于安全模式,這時只需要等待17秒即可,也可以通過下面的命令退出安全模式:

?

hadoop dfsadmin –safemode enter

?

  成功退出安全模式結(jié)果如圖5-2-2所示。

?

  

圖5-2-2 成功退出安全模式

  3)進入安全模式

  在必要情況下,可以通過以下命令把HDFS置于安全模式:

?

hadoop dfsadmin –safemode enter

?

  執(zhí)行結(jié)果如圖5-2-3所示。

?

  

圖5-2-3 進入HDFS安全模式

  4)添加節(jié)點

  可擴展性是HDFS的一個重要特性,向HDFS集群中添加節(jié)點是很容易實現(xiàn)的。添加一個新的DataNode節(jié)點,首先在新加節(jié)點上安裝好Hadoop,要和NameNode使用相同的配置(可以直接從NameNode復制),修改"/usr/hadoop/conf/master"文件,加入NameNode主機名。然后在NameNode節(jié)點上修改"/usr/hadoop/conf/slaves"文件,加入新節(jié)點主機名,再建立到新加點無密碼的SSH連接,運行啟動命令:

?

start-all.sh

?

  5)負載均衡

  HDFS的數(shù)據(jù)在各個DataNode中的分布肯能很不均勻,尤其是在DataNode節(jié)點出現(xiàn)故障新增DataNode節(jié)點時。新增數(shù)據(jù)塊時NameNode對DataNode節(jié)點的選擇策略也有可能導致數(shù)據(jù)塊分布的不均勻。用戶可以使用命令重新平衡DataNode上的數(shù)據(jù)塊的分布:

?

start-balancer.sh

?

  執(zhí)行命令前,DataNode節(jié)點上數(shù)據(jù)分布情況如圖5-2-4所示。

?

  

?

  負載均衡完畢后,DataNode節(jié)點上數(shù)據(jù)的分布情況如圖5-2-5所示。

?

  

?

  執(zhí)行負載均衡命令如圖5-2-6所示。

?

  

?

6、HDFS API詳解

  Hadoop中關(guān)于文件操作類基本上全部是在"org.apache.hadoop.fs"包中,這些API能夠支持的操作包含:打開文件,讀寫文件,刪除文件等。

Hadoop類庫中最終面向用戶提供的接口類FileSystem,該類是個抽象類,只能通過來類的get方法得到具體類。get方法存在幾個重載版本,常用的是這個:

?

static FileSystem get(Configuration conf);

?

  該類封裝了幾乎所有的文件操作,例如mkdir,delete等。綜上基本上可以得出操作文件的程序庫框架:

?

operator()

{

??? 得到Configuration對象

??? 得到FileSystem對象

??? 進行文件操作

}

?

6.1 上傳本地文件

  通過"FileSystem.copyFromLocalFile(Path src,Patch dst)"可將本地文件上傳HDFS的制定位置上,其中src和dst均為文件的完整路徑。具體事例如下:

?

package?com.hebut.file;

?

import?org.apache.hadoop.conf.Configuration;

import?org.apache.hadoop.fs.FileStatus;

import?org.apache.hadoop.fs.FileSystem;

import?org.apache.hadoop.fs.Path;

?

public?class?CopyFile {

????public?static?void?main(String[] args)?throws?Exception {

??????? Configuration conf=new?Configuration();

??????? FileSystem hdfs=FileSystem.get(conf);

???????

????????//本地文件

??????? Path src =new?Path("D:\\HebutWinOS");

????????//HDFS為止

??????? Path dst =new?Path("/");

???????

??????? hdfs.copyFromLocalFile(src, dst);

??????? System.out.println("Upload to"+conf.get("fs.default.name"));

???????

??????? FileStatus files[]=hdfs.listStatus(dst);

????????for(FileStatus file:files){

??????????? System.out.println(file.getPath());

??????? }

??? }

}

?

  運行結(jié)果可以通過控制臺、項目瀏覽器和SecureCRT查看,如圖6-1-1、圖6-1-2、圖6-1-3所示。

  1)控制臺結(jié)果

?

  

圖6-1-1 運行結(jié)果(1)

  2)項目瀏覽器

?

  

圖6-1-2 運行結(jié)果(2)

  3)SecureCRT結(jié)果

?

  

圖6-1-3 運行結(jié)果(3)

6.2 創(chuàng)建HDFS文件

  通過"FileSystem.create(Path f)"可在HDFS上創(chuàng)建文件,其中f為文件的完整路徑。具體實現(xiàn)如下:

?

package?com.hebut.file;

?

import?org.apache.hadoop.conf.Configuration;

import?org.apache.hadoop.fs.FSDataOutputStream;

import?org.apache.hadoop.fs.FileSystem;

import?org.apache.hadoop.fs.Path;

?

public?class?CreateFile {

?

????public?static?void?main(String[] args)?throws?Exception {

??????? Configuration conf=new?Configuration();

??????? FileSystem hdfs=FileSystem.get(conf);

???????

????????byte[] buff="hello hadoop world!\n".getBytes();

???????

??????? Path dfs=new?Path("/test");

???????

??????? FSDataOutputStream outputStream=hdfs.create(dfs);

??????? outputStream.write(buff,0,buff.length);

???????

??? }

}

?

  運行結(jié)果如圖6-2-1和圖6-2-2所示。

  1)項目瀏覽器

?

  

圖6-2-1 運行結(jié)果(1)

  2)SecureCRT結(jié)果

?

  

圖6-2-2 運行結(jié)果(2)

6.3 創(chuàng)建HDFS目錄

  通過"FileSystem.mkdirs(Path f)"可在HDFS上創(chuàng)建文件夾,其中f為文件夾的完整路徑。具體實現(xiàn)如下:

?

package?com.hebut.dir;

?

import?org.apache.hadoop.conf.Configuration;

import?org.apache.hadoop.fs.FileSystem;

import?org.apache.hadoop.fs.Path;

?

public?class?CreateDir {

?

????public?static?void?main(String[] args)?throws?Exception{

??????? Configuration conf=new?Configuration();

??????? FileSystem hdfs=FileSystem.get(conf);

???????

??????? Path dfs=new?Path("/TestDir");

???????

??????? hdfs.mkdirs(dfs);

?

??? }

}

?

  運行結(jié)果如圖6-3-1和圖6-3-2所示。

  1)項目瀏覽器

?

  

圖6-3-1 運行結(jié)果(1)

  2)SecureCRT結(jié)果

?

  

圖6-3-2 運行結(jié)果(2)

6.4 重命名HDFS文件

  通過"FileSystem.rename(Path src,Path dst)"可為指定的HDFS文件重命名,其中src和dst均為文件的完整路徑。具體實現(xiàn)如下:

?

package?com.hebut.file;

?

import?org.apache.hadoop.conf.Configuration;

import?org.apache.hadoop.fs.FileSystem;

import?org.apache.hadoop.fs.Path;

?

public?class?Rename{

????public?static?void?main(String[] args)?throws?Exception {

??????? Configuration conf=new?Configuration();

??????? FileSystem hdfs=FileSystem.get(conf);

?????

??????? Path frpaht=new?Path("/test");????//舊的文件名

??????? Path topath=new?Path("/test1");????//新的文件名

???????

????????boolean?isRename=hdfs.rename(frpaht, topath);

???????

??????? String result=isRename?"成功":"失敗";

??????? System.out.println("文件重命名結(jié)果為:"+result);

???????

??? }

}

?

  運行結(jié)果如圖6-4-1和圖6-4-2所示。

  1)項目瀏覽器

?

  

圖6-4-1 運行結(jié)果(1)

????2)SecureCRT結(jié)果

?

  

圖6-4-2 運行結(jié)果(2)

6.5 刪除HDFS上的文件

  通過"FileSystem.delete(Path f,Boolean recursive)"可刪除指定的HDFS文件,其中f為需要刪除文件的完整路徑,recuresive用來確定是否進行遞歸刪除。具體實現(xiàn)如下:

?

package?com.hebut.file;

?

import?org.apache.hadoop.conf.Configuration;

import?org.apache.hadoop.fs.FileSystem;

import?org.apache.hadoop.fs.Path;

?

public?class?DeleteFile {

?

????public?static?void?main(String[] args)?throws?Exception {

??????? Configuration conf=new?Configuration();

??????? FileSystem hdfs=FileSystem.get(conf);

???????

??????? Path delef=new?Path("/test1");

???????

????????boolean?isDeleted=hdfs.delete(delef,false);

????????//遞歸刪除

????????//boolean isDeleted=hdfs.delete(delef,true);

??????? System.out.println("Delete?"+isDeleted);

??? }

}

?

  運行結(jié)果如圖6-5-1和圖6-5-2所示。

  1)控制臺結(jié)果

?

  

圖6-5-1 運行結(jié)果(1)

????2)項目瀏覽器

  

圖6-5-2 運行結(jié)果(2)

6.6 刪除HDFS上的目錄

  同刪除文件代碼一樣,只是換成刪除目錄路徑即可,如果目錄下有文件,要進行遞歸刪除。

6.7 查看某個HDFS文件是否存在

  通過"FileSystem.exists(Path f)"可查看指定HDFS文件是否存在,其中f為文件的完整路徑。具體實現(xiàn)如下:

?

package?com.hebut.file;

?

import?org.apache.hadoop.conf.Configuration;

import?org.apache.hadoop.fs.FileSystem;

import?org.apache.hadoop.fs.Path;

?

public?class?CheckFile {

????public?static?void?main(String[] args)?throws?Exception {

??????? Configuration conf=new?Configuration();

??????? FileSystem hdfs=FileSystem.get(conf);

??????? Path findf=new?Path("/test1");

????????boolean?isExists=hdfs.exists(findf);

??????? System.out.println("Exist?"+isExists);

??? }

}

?

  運行結(jié)果如圖6-7-1和圖6-7-2所示。

  1)控制臺結(jié)果

?

  

圖6-7-1 運行結(jié)果(1)

  2)項目瀏覽器

?

  

圖6-7-2 運行結(jié)果(2)

6.8 查看HDFS文件的最后修改時間

  通過"FileSystem.getModificationTime()"可查看指定HDFS文件的修改時間。具體實現(xiàn)如下:

?

package?com.hebut.file;

?

import?org.apache.hadoop.conf.Configuration;

import?org.apache.hadoop.fs.FileStatus;

import?org.apache.hadoop.fs.FileSystem;

import?org.apache.hadoop.fs.Path;

?

public?class?GetLTime {

?

????public?static?void?main(String[] args)?throws?Exception {

??????? Configuration conf=new?Configuration();

??????? FileSystem hdfs=FileSystem.get(conf);

???????

??????? Path fpath =new?Path("/user/hadoop/test/file1.txt");

???????

??????? FileStatus fileStatus=hdfs.getFileStatus(fpath);

????????long?modiTime=fileStatus.getModificationTime();

???????

??????? System.out.println("file1.txt的修改時間是"+modiTime);

??? }

}

?

  運行結(jié)果如圖6-8-1所示。

?

  

圖6-8-1 控制臺結(jié)果

6.9 讀取HDFS某個目錄下的所有文件

  通過"FileStatus.getPath()"可查看指定HDFS中某個目錄下所有文件。具體實現(xiàn)如下:

?

package?com.hebut.file;

?

import?org.apache.hadoop.conf.Configuration;

import?org.apache.hadoop.fs.FileStatus;

import?org.apache.hadoop.fs.FileSystem;

import?org.apache.hadoop.fs.Path;

?

public?class?ListAllFile {

????public?static?void?main(String[] args)?throws?Exception {

??????? Configuration conf=new?Configuration();

??????? FileSystem hdfs=FileSystem.get(conf);

???????

??????? Path listf =new?Path("/user/hadoop/test");

???????

??????? FileStatus stats[]=hdfs.listStatus(listf);

????????for(int?i = 0; i < stats.length; ++i)

     {

       System.out.println(stats[i].getPath().toString());

     }

??????? hdfs.close();

??? }

}

?

  運行結(jié)果如圖6-9-1和圖6-9-2所示。

  1)控制臺結(jié)果

?

  

圖6-9-1 運行結(jié)果(1)

?

  2)項目瀏覽器

?

  

圖6-9-2 運行結(jié)果(2)

6.10 查找某個文件在HDFS集群的位置

  通過"FileSystem.getFileBlockLocation(FileStatus file,long start,long len)"可查找指定文件在HDFS集群上的位置,其中file為文件的完整路徑,start和len來標識查找文件的路徑。具體實現(xiàn)如下:

?

package?com.hebut.file;

?

import?org.apache.hadoop.conf.Configuration;

import?org.apache.hadoop.fs.BlockLocation;

import?org.apache.hadoop.fs.FileStatus;

import?org.apache.hadoop.fs.FileSystem;

import?org.apache.hadoop.fs.Path;

?

public?class?FileLoc {

????public?static?void?main(String[] args)?throws?Exception {

??????? Configuration conf=new?Configuration();

??????? FileSystem hdfs=FileSystem.get(conf);

??????? Path fpath=new?Path("/user/hadoop/cygwin");

???????

??????? FileStatus filestatus = hdfs.getFileStatus(fpath);

??????? BlockLocation[] blkLocations = hdfs.getFileBlockLocations(filestatus, 0, filestatus.getLen());

?

????????int?blockLen = blkLocations.length;

????????for(int?i=0;i<blockLen;i++){

??????????? String[] hosts = blkLocations[i].getHosts();

??????????? System.out.println("block_"+i+"_location:"+hosts[0]);

??????? }

??? }

}

?

  運行結(jié)果如圖6-10-1和6.10.2所示。

  1)控制臺結(jié)果

?

  

圖6-10-1 運行結(jié)果(1)

  2)項目瀏覽器

?

  

圖6-10-2 運行結(jié)果(2)

6.11 獲取HDFS集群上所有節(jié)點名稱信息

  通過"DatanodeInfo.getHostName()"可獲取HDFS集群上的所有節(jié)點名稱。具體實現(xiàn)如下:

?

package?com.hebut.file;

?

import?org.apache.hadoop.conf.Configuration;

import?org.apache.hadoop.fs.FileSystem;

import?org.apache.hadoop.hdfs.DistributedFileSystem;

import?org.apache.hadoop.hdfs.protocol.DatanodeInfo;

?

public?class?GetList {

?

????public?static?void?main(String[] args)?throws?Exception {

??????? Configuration conf=new?Configuration();

??????? FileSystem fs=FileSystem.get(conf);

???????

??????? DistributedFileSystem hdfs = (DistributedFileSystem)fs;

??????? DatanodeInfo[] dataNodeStats = hdfs.getDataNodeStats();

???????

????????for(int?i=0;i<dataNodeStats.length;i++){

??????????? System.out.println("DataNode_"+i+"_Name:"+dataNodeStats[i].getHostName());

??????? }

??? }

}

?

  運行結(jié)果如圖6-11-1所示。

?

  

圖6-11-1 控制臺結(jié)果

7、HDFS的讀寫數(shù)據(jù)流

7.1 文件的讀取剖析

  

?

  文件讀取的過程如下:

  1)解釋一

  • 客戶端(client)用FileSystem的open()函數(shù)打開文件。
  • DistributedFileSystem用RPC調(diào)用元數(shù)據(jù)節(jié)點,得到文件的數(shù)據(jù)塊信息。
  • 對于每一個數(shù)據(jù)塊,元數(shù)據(jù)節(jié)點返回保存數(shù)據(jù)塊的數(shù)據(jù)節(jié)點的地址。
  • DistributedFileSystem返回FSDataInputStream給客戶端,用來讀取數(shù)據(jù)。
  • 客戶端調(diào)用stream的read()函數(shù)開始讀取數(shù)據(jù)。
  • DFSInputStream連接保存此文件第一個數(shù)據(jù)塊的最近的數(shù)據(jù)節(jié)點。
  • Data從數(shù)據(jù)節(jié)點讀到客戶端(client)。
  • 當此數(shù)據(jù)塊讀取完畢時,DFSInputStream關(guān)閉和此數(shù)據(jù)節(jié)點的連接,然后連接此文件下一個數(shù)據(jù)塊的最近的數(shù)據(jù)節(jié)點。
  • 當客戶端讀取完畢數(shù)據(jù)的時候,調(diào)用FSDataInputStream的close函數(shù)。
  • 在讀取數(shù)據(jù)的過程中,如果客戶端在與數(shù)據(jù)節(jié)點通信出現(xiàn)錯誤,則嘗試連接包含此數(shù)據(jù)塊的下一個數(shù)據(jù)節(jié)點。
  • 失敗的數(shù)據(jù)節(jié)點將被記錄,以后不再連接。

  2)解釋二

  • 使用HDFS提供的客戶端開發(fā)庫,向遠程的Namenode發(fā)起RPC請求;
  • Namenode會視情況返回文件的部分或者全部block列表,對于每個block,Namenode都會返回有該block拷貝的datanode地址;
  • 客戶端開發(fā)庫會選取離客戶端最接近的datanode來讀取block;
  • 讀取完當前block的數(shù)據(jù)后,關(guān)閉與當前的datanode連接,并為讀取下一個block尋找最佳的datanode;
  • 當讀完列表的block后,且文件讀取還沒有結(jié)束,客戶端開發(fā)庫會繼續(xù)向Namenode獲取下一批的block列表。
  • 讀取完一個block都會進行checksum驗證,如果讀取datanode時出現(xiàn)錯誤,客戶端會通知Namenode,然后再從下一個擁有該block拷貝的datanode繼續(xù)讀。

7.2 文件的寫入剖析

  

?

  寫入文件的過程比讀取較為復雜:

  1)解釋一

  • 客戶端調(diào)用create()來創(chuàng)建文件
  • DistributedFileSystem用RPC調(diào)用元數(shù)據(jù)節(jié)點,在文件系統(tǒng)的命名空間中創(chuàng)建一個新的文件。
  • 元數(shù)據(jù)節(jié)點首先確定文件原來不存在,并且客戶端有創(chuàng)建文件的權(quán)限,然后創(chuàng)建新文件。
  • DistributedFileSystem返回DFSOutputStream,客戶端用于寫數(shù)據(jù)。
  • 客戶端開始寫入數(shù)據(jù),DFSOutputStream將數(shù)據(jù)分成塊,寫入data queue。
  • Data queue由Data Streamer讀取,并通知元數(shù)據(jù)節(jié)點分配數(shù)據(jù)節(jié)點,用來存儲數(shù)據(jù)塊(每塊默認復制3塊)。分配的數(shù)據(jù)節(jié)點放在一個pipeline里。
  • Data Streamer將數(shù)據(jù)塊寫入pipeline中的第一個數(shù)據(jù)節(jié)點。第一個數(shù)據(jù)節(jié)點將數(shù)據(jù)塊發(fā)送給第二個數(shù)據(jù)節(jié)點。第二個數(shù)據(jù)節(jié)點將數(shù)據(jù)發(fā)送給第三個數(shù)據(jù)節(jié)點。
  • DFSOutputStream為發(fā)出去的數(shù)據(jù)塊保存了ack queue,等待pipeline中的數(shù)據(jù)節(jié)點告知數(shù)據(jù)已經(jīng)寫入成功。
  • 如果數(shù)據(jù)節(jié)點在寫入的過程中失敗:
    • 關(guān)閉pipeline,將ack queue中的數(shù)據(jù)塊放入data queue的開始。
    • 當前的數(shù)據(jù)塊在已經(jīng)寫入的數(shù)據(jù)節(jié)點中被元數(shù)據(jù)節(jié)點賦予新的標示,則錯誤節(jié)點重啟后能夠察覺其數(shù)據(jù)塊是過時的,會被刪除。
    • 失敗的數(shù)據(jù)節(jié)點從pipeline中移除,另外的數(shù)據(jù)塊則寫入pipeline中的另外兩個數(shù)據(jù)節(jié)點。
    • 元數(shù)據(jù)節(jié)點則被通知此數(shù)據(jù)塊是復制塊數(shù)不足,將來會再創(chuàng)建第三份備份。
  • 當客戶端結(jié)束寫入數(shù)據(jù),則調(diào)用stream的close函數(shù)。此操作將所有的數(shù)據(jù)塊寫入pipeline中的數(shù)據(jù)節(jié)點,并等待ack queue返回成功。最后通知元數(shù)據(jù)節(jié)點寫入完畢。

  2)解釋二

  • 使用HDFS提供的客戶端開發(fā)庫,向遠程的Namenode發(fā)起RPC請求;
  • Namenode會檢查要創(chuàng)建的文件是否已經(jīng)存在,創(chuàng)建者是否有權(quán)限進行操作,成功則會為文件創(chuàng)建一個記錄,否則會讓客戶端拋出異常;
  • 當客戶端開始寫入文件的時候,開發(fā)庫會將文件切分成多個packets,并在內(nèi)部以"data queue"的形式管理這些packets,并向Namenode申請新的blocks,獲取用來存儲replicas的合適的datanodes列表,列表的大小根據(jù)在Namenode中對replication的設(shè)置而定。
  • 開始以pipeline(管道)的形式將packet寫入所有的replicas中。開發(fā)庫把packet以流的方式寫入第一個datanode,該datanode把該packet存儲之后,再將其傳遞給在此pipeline中的下一個datanode,直到最后一個datanode,這種寫數(shù)據(jù)的方式呈流水線的形式。
  • 最后一個datanode成功存儲之后會返回一個ack packet,在pipeline里傳遞至客戶端,在客戶端的開發(fā)庫內(nèi)部維護著"ack queue",成功收到datanode返回的ack packet后會從"ack queue"移除相應(yīng)的packet。
  • 如果傳輸過程中,有某個datanode出現(xiàn)了故障,那么當前的pipeline會被關(guān)閉,出現(xiàn)故障的datanode會從當前的pipeline中移除,剩余的block會繼續(xù)剩下的datanode中繼續(xù)以pipeline的形式傳輸,同時Namenode會分配一個新的datanode,保持replicas設(shè)定的數(shù)量。

總結(jié)

以上是生活随笔為你收集整理的HDFS初探之旅的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。