第三章 分布式文件系統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> |
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(); } |
- 文件下載
@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(false, new 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頁面