HDFS具體內容詳解


第三章 分布式文件系統HDFS

3.1 HDFS簡介

HDFS(Hadoop Distributed File System)是Hadoop項目的核心子項目,是分布式計算中數據存儲管理的基礎,是基於流數據模式訪問和處理超大文件的需求而開發的,可以運行於廉價的商用服務器上。它所具有的高容錯、高可靠性、高可擴展性、高獲得性、高吞吐率等特征,為海量數據提供了不怕故障的存儲。

3.2 HDFS 結構和工作機制

HDFS集群包括,NameNode和DataNode以及Secondary Namenode。

3.2.1 NameNode和SecondaryNameNode的作用

NameNode負責管理整個文件系統的元數據,以及每一個路徑(文件)所對應的數據塊信息,主要三個功能,分別是

(1) 管理元數據  

(2) 維護目錄樹

(3) 響應客戶請求

Secondary NameNode用來監控HDFS狀態的輔助后台程序,每隔一段時間獲取HDFS元數據的快照。

3.2.2 NameNode和Secondary NameNode工作機制

 

1.鏡像文件和編輯日志文件

1)第一階段:namenode啟動

(1)第一次啟動namenode格式化后,創建fsimage和edits文件。如果不是第一次啟動,直接加載編輯日志(edits)和鏡像文件(fsimage)到內存

(2)客戶端對元數據進行增刪改的請求

(3)namenode記錄操作日志,更新滾動日志

(4)namenode在內存中對數據進行增刪改查

2)第二階段:Secondary NameNode工作

(1)Secondary NameNode詢問namenode是否需要checkpoint。直接帶回namenode是否檢查結果。

(2)Secondary NameNode請求執行checkpoint。

(3)namenode滾動正在寫的edits日志

(4)將滾動前的編輯日志和鏡像文件拷貝到Secondary NameNode

(5)Secondary NameNode加載編輯日志和鏡像文件到內存,並合並。

(6)生成新的鏡像文件fsimage.chkpoint

(7)拷貝fsimage.chkpoint到namenode

(8)namenode將fsimage.chkpoint重新命名成fsimage

3)chkpoint檢查時間參數設置

(1)通常情況下,SecondaryNameNode每隔一小時執行一次。

在hadoop的配置文件下/opt/module/hadoop-2.8.4/etc/confs路徑下[hdfs-default.xml]

<property>

  <name>dfs.namenode.checkpoint.period</name>

  <value>3600</value>

</property>

(2)一分鍾檢查一次操作次數,當操作次數達到1百萬時,SecondaryNameNode執行一次。

<property>

  <name>dfs.namenode.checkpoint.txns</name>

  <value>1000000</value>

<description>操作動作次數</description>

</property>

 

<property>

  <name>dfs.namenode.checkpoint.check.period</name>

  <value>60</value>

<description> 1分鍾檢查一次操作次數</description>

</property>

2.鏡像文件和編輯日志文件

1)概念

namenode被格式化之后,將在/opt/module/hadoop-2.8.4/data/dfs/name/current目錄中產生如下文件,注只能在NameNode所在的節點才能找到此文件

可以執行find . -name edits* 來查找文件

edits_0000000000000000000

fsimage_0000000000000000000.md5

seen_txid

VERSION

(1)Fsimage文件:HDFS文件系統元數據的一個永久性的檢查點,其中包含HDFS文件系統的所有目錄和文件idnode的序列化信息。 

(2)Edits文件:存放HDFS文件系統的所有更新操作的路徑,文件系統客戶端執行的所有寫操作首先會被記錄到edits文件中。 

(3)seen_txid文件保存的是一個數字,就是最后一個edits_的數字

(4)每次Namenode啟動的時候都會將fsimage文件讀入內存,並從00001開始到seen_txid中記錄的數字依次執行每個edits里面的更新操作,保證內存中的元數據信息是最新的、同步的,可以看成Namenode啟動的時候就將fsimage和edits文件進行了合並。

2)oiv查看fsimage文件

(1)查看oiv和oev命令

[jareny@bigdata111 current]$ hdfs

oiv                  apply the offline fsimage viewer to an fsimage

oev                  apply the offline edits viewer to an edits file

(2)基本語法

hdfs oiv -p 文件類型 -i鏡像文件 -o 轉換后文件輸出路徑

(3)案例實操

[jareny@bigdata111 current]$ pwd

/opt/module/hadoop-2.8.4/data/dfs/name/current

 

[jareny@bigdata111 current]$ hdfs oiv -p XML -i fsimage_0000000000000000316 -o /opt/fsimage.xml

 

[jareny@bigdata111 current]$ cat /opt/module/hadoop-2.8.4/fsimage.xml

將顯示的xml文件內容拷貝到IDEA中創建的xml文件中,並格式化。

 

3)oev查看edits文件

(1)基本語法

hdfs oev -p 文件類型 -i編輯日志 -o 轉換后文件輸出路徑

-p –processor <arg>   指定轉換類型: binary (二進制格式), xml (默認,XML格式),stats

-i –inputFile <arg>     輸入edits文件,如果是xml后綴,表示XML格式,其他表示二進制

-o –outputFile <arg> 輸出文件,如果存在,則會覆蓋

(2)案例實操

[jareny@bigdata111 current]$ hdfs oev -p XML -i edits_0000000000000000135-0000000000000000135 -o /opt/module/hadoop-2.8.4/edits.xml -p stats

[jareny@bigdata111 current]$ cat /opt/module/hadoop-2.8.4/edits.xml

 

每個RECORD記錄了一次操作,比如圖中的

OP_ADD代表添加文件操作、OP_MKDIR代表創建目錄操作。里面還記錄了

文件路徑(PATH)

修改時間(MTIME)

添加時間(ATIME)

客戶端名稱(CLIENT_NAME)

客戶端地址(CLIENT_MACHINE)

權限(PERMISSION_STATUS)等非常有用的信息

 

將顯示的xml文件內容拷貝到IDEA中創建的xml文件中,並格式化。

3.滾動編輯日志

正常情況HDFS文件系統有更新操作時,就會滾動編輯日志。也可以用命令強制滾動編輯日志。

1)滾動編輯日志(前提必須啟動集群)

[jareny@bigdata111 current]$ hdfs dfsadmin -rollEdits

 

舉例:原文件名edits_inprogress_0000000000000000321

執行以下命令后

[root@bigdata111 current]# hdfs dfsadmin -rollEdits

Successfully rolled edit logs.

New segment starts at txid 323

edits_inprogress_0000000000000000321 => edits_inprogress_0000000000000000323

2)鏡像文件什么時候產生

Namenode啟動時加載鏡像文件和編輯日志

4 .namenode版本號

1)查看namenode版本號

在/opt/module/hadoop-2.8.4/data/dfs/name/current這個目錄下查看VERSION

namespaceID=1778616660

clusterID=CID-bc165781-d10a-46b2-9b6f-3beb1d988fe0

cTime=1552918200296

storageType=NAME_NODE

blockpoolID=BP-274621862-192.168.1.111-1552918200296

layoutVersion=-63

2)namenode版本號具體解釋

(1) namespaceID在HDFS上,會有多個Namenode,所以不同Namenode的namespaceID是不同的,分別管理一組blockpoolID。

(2)clusterID集群id,全局唯一

(3)cTime屬性標記了namenode存儲系統的創建時間,對於剛剛格式化的存儲系統,這個屬性為0;但是在文件系統升級之后,該值會更新到新的時間戳。

(4)storageType屬性說明該存儲目錄包含的是namenode的數據結構。

(5)blockpoolID:一個block pool id標識一個block pool,並且是跨集群的全局唯一。當一個新的Namespace被創建的時候(format過程的一部分)會創建並持久化一個唯一ID。在創建過程構建全局唯一的BlockPoolID比人為的配置更可靠一些。NN將BlockPoolID持久化到磁盤中,在后續的啟動過程中,會再次load並使用。

(6)layoutVersion是一個負整數。通常只有HDFS增加新特性時才會更新這個版本號。

(7)storageID (存儲ID):是DataNode的ID,不唯一

5. SecondaryNameNode目錄結構

Secondary NameNode用來監控HDFS狀態的輔助后台程序,每隔一段時間獲取HDFS元數據的快照。

在/opt/module/hadoop-2.8.4/data/dfs/namesecondary/current這個目錄中查看SecondaryNameNode目錄結構。

edits_0000000000000000001-0000000000000000002

fsimage_0000000000000000002

fsimage_0000000000000000002.md5

VERSION

SecondaryNameNode的namesecondary/current目錄和主namenode的current目錄的布局相同。

好處:在主namenode發生故障時(假設沒有及時備份數據),可以從SecondaryNameNode恢復數據。

方法一:將SecondaryNameNode中數據拷貝到namenode存儲數據的目錄;

方法二:使用-importCheckpoint選項啟動namenode守護進程,從而將SecondaryNameNode中數據拷貝到namenode目錄中。

1)案例實操(一):

模擬namenode故障,並采用方法一,恢復namenode數據

(1)kill -9 namenode進程

(2)刪除namenode存儲的數據(/opt/module/hadoop-2.8.4/data/dfs/name)

rm -rf /opt/module/hadoop-2.8.4/data/dfs/name/*

 

注:此時hadoop-daemon.sh stop namenode關閉NN,

然后hadoop-daemon.sh start namenode重啟NN,發現50070頁面啟動不了

(3)拷貝SecondaryNameNode中數據到原namenode存儲數據目錄

cp -r /opt/module/hadoop-2.8.4/data/dfs/namesecondary/* /opt/module/hadoop-2.8.4/data/dfs/name/

(4)重新啟動namenode

sbin/hadoop-daemon.sh start namenode

2)案例實操(二):

模擬namenode故障,並采用方法二,恢復namenode數據

(0)修改hdfs-site.xml中的配置,value的單位是秒,默認3600,即1小時,僅配置一台即可

<property>

  <name>dfs.namenode.checkpoint.period</name>

  <value>120</value>

</property>

 

<property>

  <name>dfs.namenode.name.dir</name>

  <value>/opt/module/hadoop-2.8.4/data/dfs/name</value>

</property>

(1)kill -9 namenode進程

(2)刪除namenode存儲的數據(/opt/module/hadoop-2.8.4/data/dfs/name)

rm -rf /opt/module/hadoop-2.8.4/data/dfs/name/*

(3)如果SecondaryNameNode不和Namenode在一個主機節點上,需要將SecondaryNameNode存儲數據的目錄拷貝到Namenode存儲數據的平級目錄。

[jareny@bigdata111 dfs]$ pwd

/opt/module/hadoop-2.8.4/data/dfs

[jareny@bigdata111 dfs]$ ls

data  name  namesecondary

(4)導入檢查點數據(等待一會ctrl+c結束掉)

bin/hdfs namenode -importCheckpoint

(5)啟動namenode

sbin/hadoop-daemon.sh start namenode

(6)如果提示文件鎖了,可以刪除in_use.lock

rm -rf /opt/module/hadoop-2.8.4/data/dfs/namesecondary/in_use.lock

6.集群安全模式操作

1)概述

Namenode啟動時,首先將映像文件(fsimage)載入內存,並執行編輯日志(edits)中的各項操作。一旦在內存中成功建立文件系統元數據的映像,則創建一個新的fsimage文件和一個空的編輯日志。此時,namenode開始監聽datanode請求。但是此刻,namenode運行在安全模式,即namenode的文件系統對於客戶端來說是只讀的。

系統中的數據塊的位置並不是由namenode維護的,而是以塊列表的形式存儲在datanode中。在系統的正常操作期間,namenode會在內存中保留所有塊位置的映射信息。在安全模式下,各個datanode會向namenode發送最新的塊列表信息,namenode了解到足夠多的塊位置信息之后,即可高效運行文件系統。

如果滿足“最小副本條件”,namenode會在30秒鍾之后就退出安全模式。所謂的最小副本條件指的是在整個文件系統中99.9%的塊滿足最小副本級別(默認值:dfs.replication.min=1)。在啟動一個剛剛格式化的HDFS集群時,因為系統中還沒有任何塊,所以namenode不會進入安全模式。

2)基本語法

集群處於安全模式,不能執行重要操作(寫操作)。集群啟動完成后,自動退出安全模式。

(1)bin/hdfs dfsadmin -safemode get (功能描述:查看安全模式狀態)

(2)bin/hdfs dfsadmin -safemode enter   (功能描述:進入安全模式狀態)

(3)bin/hdfs dfsadmin -safemode leave (功能描述:離開安全模式狀態)

(4)bin/hdfs dfsadmin -safemode wait (功能描述:等待安全模式狀態)

3)案例

模擬等待安全模式

1)先進入安全模式

bin/hdfs dfsadmin -safemode enter

2)執行下面的腳本

編輯一個腳本(注:必須已設置環境變量,要不就寫絕對路徑)

#!bin/bash

hdfs dfsadmin -safemode wait

hadoop fs -put /opt/BBB /

3)再打開一個窗口,執行

bin/hdfs dfsadmin -safemode leave

7.Namenode多目錄配置

1)namenode的本地目錄可以配置成多個,且每個目錄存放內容相同,增加了可靠性。

2)具體配置如下:

hdfs-site.xml

<property>

    <name>dfs.namenode.name.dir</name>

<value>file:///${hadoop.tmp.dir}/dfs/name1,file:///${hadoop.tmp.dir}/dfs/name2</value>

</property>

  1. 停止集群 刪除data 和 logs  rm -rf data/* logs/*
  2. hdfs namenode -format
  3. start-dfs.sh
  4. 去展示

https://blog.csdn.net/qq_39657909/article/details/85553525

實驗總結:

思考1:如果在非Namenode節點、進行格式化(hdfs namenode -format)

是否和在NN節點上同樣會生成name1和name2目錄呢?

    答:只要配置了以上得配置,在該節點下同樣會生成name1和name2

具體解釋:

格式化做了哪些事情?

在NameNode節點上,有兩個最重要的路徑,分別被用來存儲元數據信息和操作日志,而這兩個路徑來自於配置文件,它們對應的屬性分別是dfs.name.dir和dfs.name.edits.dir,同時,它們默認的路徑均是/tmp/hadoop/dfs/name。格式化時,NameNode會清空兩個目錄下的所有文件,之后,格式化會在目錄dfs.name.dir下創建文件

hadoop.tmp.dir 這個配置,會讓dfs.name.dir和dfs.name.edits.dir會讓兩個目錄的文件生成在一個目錄里

 

思考2:非NN上如果生成了name1和name2,那么他和NN上生成得有沒有差別?

答:有區別、NN節點上會產生新得edits_XXX,非NN不會fsimage會更新,而非NN不會,只會產生一個僅初始化得到得fsimage,不會生成edits,更不會發生日志滾動。

3.2.3 DataNode 的作用

作用DataNode 負責管理用戶的文件數據塊,每一個數據塊都可以在多個datanode上存儲多個副本。

1.NameNode & DataNode工作機制

 

1)一個數據塊在datanode上以文件形式存儲在磁盤上,包括兩個文件,一個是數據本身,一個是元數據包括數據塊的長度,塊數據的校驗和,以及時間戳。

2)DataNode啟動后向namenode注冊,通過后,周期性(1小時)的向namenode上報所有的塊信息。

3)心跳是每3秒一次,心跳返回結果帶有namenode給該datanode的命令如復制塊數據到另一台機器,或刪除某個數據塊。如果超過10分鍾沒有收到某個datanode的心跳,則認為該節點不可用。

4)集群運行中可以安全加入和退出一些機器

2.數據完整性

1)當DataNode讀取block的時候,它會計算checksum校驗和

2)如果計算后的checksum,與block創建時值不一樣,說明block已經損壞。

3)client讀取其他DataNode上的block.

4)datanode在其文件創建后周期驗證checksum校驗和

3.掉線時限參數設置

datanode進程死亡或者網絡故障造成datanode無法與namenode通信,namenode不會立即把該節點判定為死亡,要經過一段時間,這段時間暫稱作超時時長。HDFS默認的超時時長為10分鍾+30秒。如果定義超時時間為timeout,則超時時長的計算公式為:

timeout  = 2 * dfs.namenode.heartbeat.recheck-interval + 10 * dfs.heartbeat.interval。

而默認的dfs.namenode.heartbeat.recheck-interval 大小為5分鍾,dfs.heartbeat.interval默認為3秒。

需要注意的是hdfs-site.xml 配置文件中的heartbeat.recheck.interval的單位為毫秒,dfs.heartbeat.interval的單位為秒。

<property>

    <name>dfs.namenode.heartbeat.recheck-interval</name>

    <value>300000</value>

</property>

<property>

    <name> dfs.heartbeat.interval </name>

    <value>3</value>

</property>

4.DataNode的目錄結構

和namenode不同的是,datanode的存儲目錄是初始階段自動創建的,不需要額外格式化。

1)在/opt/module/hadoop-2.8.4/data/dfs/data/current這個目錄下查看版本號

[jareny@bigdata111 current]$ cat VERSION

storageID=DS-1b998a1d-71a3-43d5-82dc-c0ff3294921b

clusterID=CID-1f2bf8d1-5ad2-4202-af1c-6713ab381175

cTime=0

datanodeUuid=970b2daf-63b8-4e17-a514-d81741392165

storageType=DATA_NODE

layoutVersion=-56

2)具體解釋

(1)storageID:存儲id號

(2)clusterID集群id,全局唯一

(3)cTime屬性標記了datanode存儲系統的創建時間,對於剛剛格式化的存儲系統,這個屬性為0;但是在文件系統升級之后,該值會更新到新的時間戳。

(4)datanodeUuid:datanode的唯一識別碼

(5)storageType:存儲類型

(6)layoutVersion是一個負整數。通常只有HDFS增加新特性時才會更新這個版本號。

3)在/opt/module/hadoop-2.8.4/data/dfs/data/current/BP-97847618-192.168.10.102-1493726072779/current這個目錄下查看該數據塊的版本號

[jareny@bigdata111 current]$ cat VERSION

#Mon May 08 16:30:19 CST 2017

namespaceID=1933630176

cTime=0

blockpoolID=BP-97847618-192.168.10.102-1493726072779

layoutVersion=-56

4)具體解釋

(1)namespaceID:是datanode首次訪問namenode的時候從namenode處獲取的storageID對每個datanode來說是唯一的(但對於單個datanode中所有存儲目錄來說則是相同的),namenode可用這個屬性來區分不同datanode。

(2)cTime屬性標記了datanode存儲系統的創建時間,對於剛剛格式化的存儲系統,這個屬性為0;但是在文件系統升級之后,該值會更新到新的時間戳。

(3)blockpoolID:一個block pool id標識一個block pool,並且是跨集群的全局唯一。當一個新的Namespace被創建的時候(format過程的一部分)會創建並持久化一個唯一ID。在創建過程構建全局唯一的BlockPoolID比人為的配置更可靠一些。NN將BlockPoolID持久化到磁盤中,在后續的啟動過程中,會再次load並使用。

(4)layoutVersion是一個負整數。通常只有HDFS增加新特性時才會更新這個版本號。

5.Datanode多目錄配置

1)datanode也可以配置成多個目錄,每個目錄存儲的數據不一樣。即:數據不是副本。

2)具體配置如下:

hdfs-site.xml

<property>

        <name>dfs.datanode.data.dir</name>

  <value>file:///${hadoop.tmp.dir}/dfs/data1,file:///${hadoop.tmp.dir}/dfs/data2</value>

</property>

 

3.3 HDFS 優缺點

3.1.1HDFS優點

1.支持海量數據的存儲:HDFS存儲的文件可以支持TB和PB級別的數據。

2.檢測和快速應對硬件故障:在集群環境中,硬件故障是常見性問題,HDFS能夠通過心跳機制來檢測故障和自動恢復文件。

3.流式數據訪問:HDFS不能做到低延遲的數據訪問,但是HDFS的吞吐量大,適用於處理離線數據,不適合處理實時數據。HDFS的數據處理規模比較大,應用一次需要大量的數據,同時這些應用一般都是批量處理,而不是用戶交互式處理。應用程序能以流的形式訪問數據庫。主要的是數據的吞吐量,而不是訪問速度。

4.簡化的一致性模型:一個文件存儲在HDFS上后,HDFS對文件的切塊,文件的存儲,節點進行管理,適合一次寫入,多次讀取的場景。因為存儲在HDFS上的文件都是超大文件,hadoop1.X默認是64M。

5.高容錯性:數據自動保存多個副本,副本丟失后自動恢復。可構建在廉價的機器上,實現線性擴展。當集群增加新節點之后,namenode也可以感知,將數據分發和備份到相應的節點上。

6.商用硬件:HDFS是設計運行在廉價硬件的集群上的,因此至少對於龐大的集群來說,節點故障的幾率還是非常高的。HDFS遇到上述故障時,被設計成能夠繼續運行且不讓用戶察覺到明顯的中斷。

3.1.2 HDFS缺點

1.不能做到低延遲數據訪問:由於HDFS針對高數據吞吐量做了優化,犧牲了獲取數據的延遲,所以對於低延遲數據訪問,不適合HDFS。對於低延遲的訪問需求,HBase是更好的選擇。

2.不適合大量的小文件存儲 :由於namenode將文件系統的元數據存儲在內存中,因此該文件系統所能存儲的文件總數受限於namenode的內存容量。

3.不適合修改文件:對於上傳到HDFS上的文件,不支持修改文件。Hadoop2.0雖然支持了文件的追加功能,但是還是不建議對HDFS上的文件進行修改。因為效率低下。HDFS適合一次寫入,然后多次讀取的場景。

4.不適合結構化數據:HDFS適合存儲半結構化和非結構化數據,若有嚴格的結構化數據存儲場景,也可以考慮采用Hbase的方案。

5.不支持用戶的並行寫:同一時間內,只能有一個用戶執行寫操作。

3. 3 HDFS應用場景

HDFS 提供高吞吐量應用程序數據訪問功能,適合帶有大型數據集的應用程序,以下是一些常用的應用場景。

1.數據密集型並行計算:數據量極大,但是計算相對簡單的並行處理,如大規模Web信息搜索;

2.計算密集型並行計算:數據量相對不是很大,但是計算較為復雜的並行計算,如3D建模與渲染、氣象預報和科學計算;

3.數據密集與計算密集混合型的並行計算,如3D電影的渲染。

HDFS在使用過程中有以下限制:

4.HDFS不適合大量小文件的存儲,因NameNode將文件系統的元數據存放在內存中,因此存儲的文件數目受限於NameNode的內存大小;

5.HDFS適用於高吞吐量,而不適合低時間延遲的訪問;

6.流式讀取的方式,不適合多用戶寫入一個文件(一個文件同時只能被一個客戶端寫),以及任意位置寫入(不支持隨機寫);

7.HDFS更加適合寫入一次,讀取多次的應用場景

 

3.4 HDFS 寫入文件步驟

1.文件寫入步驟

 

1)客戶端向namenode請求上傳文件,namenode檢查目標文件是否已存在,父目錄是否存在。

2)namenode返回是否可以上傳。

3)客戶端請求第一個 block上傳到哪幾個datanode服務器上。

4)namenode返回3個datanode節點,分別為dn1、dn2、dn3。

5)客戶端請求dn1上傳數據,dn1收到請求會繼續調用dn2,然后dn2調用dn3,將這個通信管道建立完成

6)dn1、dn2、dn3逐級應答客戶端

7)客戶端開始往dn1上傳第一個block(先從磁盤讀取數據放到一個本地內存緩存),以packet為單位,dn1收到一個packet就會傳給dn2,dn2傳給dn3;dn1每傳一個packet會放入一個應答隊列等待應答

8)當一個block傳輸完成之后,客戶端再次請求namenode上傳第二個block的服務器。(重復執行3-7步)

2.網絡拓撲概念

在本地網絡中,兩個節點被稱為“彼此近鄰”是什么意思?在海量數據處理中,其主要限制因素是節點之間數據的傳輸速率——帶寬很稀缺。這里的想法是將兩個節點間的帶寬作為距離的衡量標准。

節點距離:兩個節點到達最近的共同祖先的距離總和。

例如,假設有數據中心d1機架r1中的節點n1。該節點可以表示為/d1/r1/n1。利用這種標記,這里給出四種距離描述。

Distance(/d1/r1/n1, /d1/r1/n1)=0(同一節點上的進程)

Distance(/d1/r1/n1, /d1/r1/n2)=2(同一機架上的不同節點)

Distance(/d1/r1/n1, /d1/r3/n2)=4(同一數據中心不同機架上的節點)

Distance(/d1/r1/n1, /d2/r4/n2)=6(不同數據中心的節點)

 

大家算一算每兩個節點之間的距離。

 

3.機架感知(副本節點選擇)

1)官方ip地址:

http://hadoop.apache.org/docs/r2.7.2/hadoop-project-dist/hadoop-common/RackAwareness.html

http://hadoop.apache.org/docs/r2.7.2/hadoop-project-dist/hadoop-hdfs/HdfsDesign.html#Data_Replication

2)低版本Hadoop副本節點選擇

第一個副本在client所處的節點上。如果客戶端在集群外,隨機選一個。

第二個副本和第一個副本位於不相同機架的隨機節點上。

第三個副本和第二個副本位於相同機架,節點隨機。

 

3)Hadoop2.7.2副本節點選擇

第一個副本在client所處的節點上。如果客戶端在集群外,隨機選一個。

第二個副本和第一個副本位於相同機架,隨機節點。

第三個副本位於不同機架,隨機節點。

 

3.5 HDFS 讀取文件步驟

 

1)客戶端向namenode請求下載文件,namenode通過查詢元數據,找到文件塊所在的datanode地址。

2)挑選一台datanode(就近原則,然后隨機)服務器,請求讀取數據。

3)datanode開始傳輸數據給客戶端(從磁盤里面讀取數據放入流,以packet為單位來做校驗)。

4)客戶端以packet為單位接收,先在本地緩存,然后寫入目標文件。

3.5 HDFS 項目實戰

3.5.1 項目1文件上傳和下載

1.文件上傳

@Test

public void putFileToHDFS() throws Exception{

// 1 創建配置信息對象

// new Configuration();的時候,它就會去加載jar包中的hdfs-default.xml

// 然后再加載classpath下的hdfs-site.xml

Configuration configuration = new Configuration();

 

// 2 設置參數

// 參數優先級: 1、客戶端代碼中設置的值  2、classpath下的用戶自定義配置文件 3、然后是服務器的默認配置

configuration.set("dfs.replication", "2");

 

FileSystem fs = FileSystem.get(new URI("hdfs://bigdata111:9000"),configuration, "itstar");

 

// 3 創建要上傳文件所在的本地路徑

Path src = new Path("e:/hello.txt");

 

// 4 創建要上傳到hdfs的目標路徑

Path dst = new Path("hdfs://bigdata111:9000/user/itstar/hello.txt");

 

// 5 拷貝文件

fs.copyFromLocalFile(src, dst);

fs.close();

}

 

  1. 文件下載

@Test

public void getFileFromHDFS() throws Exception{

 

// 1 創建配置信息對象

Configuration configuration = new Configuration();

 

FileSystem fs = FileSystem.get(new URI("hdfs://bigdata111:9000"),configuration, "itstar");

 

// fs.copyToLocalFile(new Path("hdfs://bigdata111:9000/user/itstar/hello.txt"), new Path("d:/hello.txt"));

// boolean delSrc 指是否將原文件刪除

// Path src 指要下載的文件路徑

// Path dst 指將文件下載到的路徑

// boolean useRawLocalFileSystem 是否開啟文件效驗

    // 2 下載文件

fs.copyToLocalFile(falsenew Path("hdfs://bigdata111:9000/user/itstar/hello.txt"), new Path("e:/hellocopy.txt"), true);

fs.close();

}

3.5.2 通過IO流操作HDFS

1.HDFS文件上傳

@Test

public void putFileToHDFS() throws Exception{

// 1 創建配置信息對象

Configuration configuration = new Configuration();

 

FileSystem fs = FileSystem.get(new URI("hdfs://bigdata111:9000"),configuration, "itstar");

 

// 2 創建輸入流

FileInputStream inStream = new FileInputStream(new File("e:/hello.txt"));

 

// 3 獲取輸出路徑

String putFileName = "hdfs://bigdata111:9000/user/itstar/hello1.txt";

Path writePath = new Path(putFileName);

 

// 4 創建輸出流

FSDataOutputStream outStream = fs.create(writePath);

 

// 5 流對接

try{

IOUtils.copyBytes(inStream, outStream, 4096, false);

}catch(Exception e){

e.printStackTrace();

}finally{

IOUtils.closeStream(inStream);

IOUtils.closeStream(outStream);

}

}

2.HDFS文件下載

@Test

public void getFileToHDFS() throws Exception{

// 1 創建配置信息對象

Configuration configuration = new Configuration();

 

FileSystem fs = FileSystem.get(new URI("hdfs://bigdata111:9000"),configuration, "itstar");

 

// 2 獲取讀取文件路徑

String filename = "hdfs://bigdata111:9000/user/itstar/hello1.txt";

 

// 3 創建讀取path

Path readPath = new Path(filename);

 

// 4 創建輸入流

FSDataInputStream inStream = fs.open(readPath);

 

// 5 流對接輸出到控制台

try{

IOUtils.copyBytes(inStream, System.out, 4096, false);

}catch(Exception e){

e.printStackTrace();

}finally{

IOUtils.closeStream(inStream);

}

}

3.5.3 項目3 HDFS 底層原理RPC

 

3.6 HDFS 的Web頁面

 

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM