1. 程式人生 > >這是一篇最通熟易懂的Hadoop HDFS實踐攻略!

這是一篇最通熟易懂的Hadoop HDFS實踐攻略!

作者介紹:杜亦舒,創業中,技術合夥人,喜歡研究分享技術。個人訂閱號:效能與架構。

  • HDFS是用來解決什麼問題?怎麼解決的?
  • 如何在命令列下操作HDFS?
  • 如何使用Java API來操作HDFS?
  • 在瞭解基本思路和操作方法後,進一步深究HDFS具體的讀寫資料流程

學習並實踐本文教程後,可以對HDFS有比較清晰的認識,並可以進行熟練操作,為後續學習Hadoop體系打好基礎。

目錄:

理論部分

  1. HDFS 基本原理
  2. 檔案讀取、寫入機制
  3. 元資料管理思路

實踐部分

  1. 安裝實踐環境
  2. Shell 命令列操作方式
  3. Java API操作方式

一、HDFS基本原理

HDFS(Hadoop Distribute File System)是一個分散式檔案系統,是Hadoop的重要成員。

1、檔案系統的問題

檔案系統是作業系統提供的磁碟空間管理服務,只需要我們制定把檔案放到哪兒,從哪個路徑讀取檔案就可以了,不用關心檔案在磁碟上是如何存放的。

當檔案所需空間大於本機磁碟空間時,如何處理呢?

一是加磁碟,但是加到一定程度就有限制了;二是加機器,用遠端共享目錄的方式提供網路化的儲存,這種方式可以理解為分散式檔案系統的雛形,可以把不同檔案放入不同的機器中,空間不足了可繼續加機器,突破了儲存空間的限制。但這個方式有多個問題:

  • 單機負載可能極高例如某個檔案是熱門,很多使用者經常讀取這個檔案,就使得次檔案所在機器的訪問壓力極高。
  • 資料不安全如果某個檔案所在的機器出現故障,這個檔案就不能訪問了,可靠性很差。
  • 檔案整理困難例如想把一些檔案的儲存位置進行調整,就需要看目標機器的空間是否夠用,並且需要自己維護檔案位置,如果機器非常多,操作就極為複雜。

2、HDFS的解決思路

HDFS是個抽象層,底層依賴很多獨立的伺服器,對外提供統一的檔案管理功能,對於使用者來講,感覺就像在操作一臺機器,感受不到HDFS下面的多臺伺服器。

例如使用者訪問HDFS中的/a/b/c.mpg這個檔案,HDFS負責從底層相應伺服器中讀取,然後返回給使用者,這樣使用者只需和HDFS打交道,不關心這個檔案是怎麼儲存的。

HDFS

例如使用者需要儲存一個檔案/a/b/xxx.avi。

HDFS首先會把這個檔案進行分割,例如分為4塊,然後分別放到不同伺服器上。

HDFS

這樣做有個好處,不怕檔案太大,並且讀檔案的壓力不會全部集中在一臺伺服器上。但如果某臺伺服器壞了,檔案就讀不全了。

HDFS為保證檔案可靠性,會把每個檔案塊進行多個備份:

  • 塊1:A B C
  • 塊2:A B D
  • 塊3:B C D
  • 塊4:A C D

這樣檔案的可靠性就大大增強了,即使某個伺服器壞了,也可以完整讀取檔案。

同時還帶來一個很大的好處,就是增加了檔案的併發訪問能力,比如多個使用者讀取這個檔案時,都要讀塊1,HDFS可以根據伺服器的繁忙程度,選擇從那臺伺服器讀塊1。

3、元資料的管理

HDFS中存了哪些檔案?

檔案被分成了哪些塊?

每個塊被放在哪臺伺服器上?

……

這些都叫做元資料,這些元資料被抽象為一個目錄樹,記錄了這些複雜的對應關係。這些元資料由一個單獨的模組進行管理,這個模組叫做NameNode。存放檔案塊的真實伺服器叫做DataNode,所以使用者訪問HDFS的過程可以理解為:

使用者-> HDFS -> NameNode -> DataNode

4、HDFS優點

  • 容量可以線性擴充套件
  • 有副本機制,儲存可靠性高,吞吐量增大
  • 有了NameNode後,使用者訪問檔案只需指定HDFS上的路徑

二、HDFS實踐

經過上面介紹,可以對HDFS有個基本的瞭解,下面開始進行實際操作,在實踐中更好的認識HDFS。

1、安裝實踐環境

您可以選擇自己搭建環境,也可以使用打包好的Hadoop環境(版本2.7.3)

這個Hadoop環境實際上是一個虛機映象,所以需要安裝virtualbox虛擬機器、vagrant映象管理工具,和我的Hadoop映象,然後用這個映象啟動虛機就可以了,下面是具體操作步驟:

1)安裝virtualbox

下載地址:https://www.virtualbox.org/wiki/Downloads

2)安裝vagrant

因為官網下載較慢,我上傳到了雲盤

Windows版

連結: https://pan.baidu.com/s/1pKKQGHl

密碼: eykr

Mac版

連結: https://pan.baidu.com/s/1slts9yt

密碼: aig4

安裝完成後,在命令列終端下就可以使用vagrant命令。

3)下載Hadoop映象

4)啟動

載入Hadoop映象

vagrant box add {自定義映象名稱} {映象所在路徑}

例如您想命名為Hadoop,映象下載後的路徑為d:\hadoop.box,載入命令就是這樣:

vagrant box add hadoop d:\hadoop.box

建立工作目錄,例如d:\hdfstest。

進入此目錄,初始化

cd d:\hdfstest

vagrant init hadoop

啟動虛機

vagrant up

啟動完成後,就可以使用SSH客戶端登入虛機了

IP   127.0.0.1

埠 2222

使用者名稱 root

密碼 vagrant

登入後使用命令ifconfig 檢視本虛機的IP(如192.168.31.239),可以使用此IP和埠22登入了

IP   192.168.31.239

埠 22

使用者名稱 root

密碼 vagrant

Hadoop伺服器環境搭建完成。

2、Shell命令列操作

登入Hadoop伺服器後,先啟動HDFS,執行命令:

start-dfs.sh

  • 檢視幫助

hdfs dfs –help

顯示目錄資訊

-ls 後面是要檢視的目錄路徑

建立目錄

建立目錄/test

hdfs dfs -mkdir /test

一次建立多級目錄/aa/bb

hdfs dfs -mkdir -p /aa/bb

  • 上傳檔案

形式

hdfs dfs -put {本地路徑} {hdfs中的路徑}

例項(先建立好一個測試檔案mytest.txt,內容隨意,然後上傳到/test)

hadoop fs    -put       ~/mytest.txt /test

  • 顯示檔案內容

hdfs dfs -cat /test/mytest.txt

  • 合併下載

先建立2個測試檔案(log.access, log.error),內容隨意,使用-put上傳到/test目錄下

hdfs dfs -put log.* /test

然後把2個log檔案合併下載到一個檔案中

hdfs dfs -getmerge /test/log.* ./log

檢視本地log檔案內容,應該包含log.access與log.error兩個檔案的內容。

  • 複製

從HDFS的一個路徑拷貝HDFS的另一個路徑

hdfs dfs -cp /test/mytest.txt /aa/mytest.txt.2

驗證

hdfs dfs -ls /aa

  • 移動檔案

hdfs dfs -mv /aa/mytest.txt.2 /aa/bb

驗證

hdfs dfs -ls /aa/bb

應列出mytest.txt.2。

  • 刪除

hdfs dfs -rm -r /aa/bb/mytest.txt.2

使用-r引數可以一次刪除多級目錄。

驗證

hdfs dfs -ls /aa/bb

應為空

  • 修改檔案許可權

與Linux檔案系統中的用法一樣,修改檔案所屬許可權

-chgrp

-chmod

-chown

示例

hdfs dfs -chmod 666 /test/mytest.txt

hdfs dfs -chown someuser:somegrp /test/mytest.txt

  • 統計檔案系統的可用空間

hdfs dfs -df -h /

  • 統計資料夾的大小

hdfs dfs -du -s -h /test

3、Java API操作

(1)環境配置

因為需要在本機連結Hadoop虛機伺服器,所以需要配置Hadoop,使其可以被外部訪問。

先登入Hadoop虛機伺服器,然後:

1)檢視本機IP

ip address

例如IP為:192.168.31.239

2)修改檔案:

vi /usr/local/hadoop-2.7.3/etc/hadoop/core-site.xml

<property>

<name>fs.defaultFS</name>

<value>hdfs://localhost:9000</value>

</property>

把其中的localhost:9000修改為本機IP 192.168.31.239:9000

3)重新啟動HDFS

#停止

stop-dfs.sh

#啟動

start-dfs.sh

(2)搭建開發環境

)新建專案目錄hdfstest

2)在專案目錄下建立pom.xml

內容:

3)建立原始碼目錄src/main/java

現在專案目錄結構

├── pom.xml

!”” src

│     └── main

│     └── java

(3)示例程式碼

檢視檔案列表ls

1)新建檔案src/main/java/Ls.java

列出/下的檔案列表,及遞迴獲取所有檔案

2)編譯執行

mvn compile

mvn exec:java -Dexec.mainClass=”Ls” -Dexec.cleanupDaemonThreads

=false

建立目錄mkdir

在HDFS中建立目錄/mkdir/a/b

1)新建檔案

src/main/java/Mkdir.java

2)編譯執行

mvn compile

mvn exec:java -Dexec.mainClass=”Mkdir” -Dexec.cleanupDaemonThre

ads=false

3)在伺服器中使用HDFS命令驗證

hdfs dfs -ls /mkdir

上傳檔案put

在當前專案目錄下新建測試檔案,上傳到HDFS中的/mkdir

1)在專案目錄下建立測試檔案testfile.txt,內容隨意

2)新建檔案src/main/java/Put.java

3)編譯執行

mvn compile

mvn exec:java -Dexec.mainClass=”Put” -Dexec.cleanupDaemonThread

s=false

4)在伺服器中使用HDFS命令驗證

hdfs dfs -ls /mkdir

hdfs dfs -cat /mkdir/testfile.txt

下載檔案get

1)新建檔案src/main/java/Get.java

把HDFS中/mkdir/testfile.txt下載到當前專案目錄下

2)編譯執行

mvn compile

mvn exec:java -Dexec.mainClass=”Get” -Dexec.cleanupDaemonThread

s=false

3)檢視專案目錄下是否存在testfile2.txt及其內容

刪除檔案delete

刪除HDFS上之前上傳的/mkdir/testfile.txt

1)新建檔案src/main/java/Del.java

2)編譯執行

mvn compile

mvn exec:java -Dexec.mainClass=”Del” -Dexec.cleanupDaemonThread

s=false

3)在伺服器中使用HDFS命令驗證,檢查testfile.txt是否被刪除

hdfs dfs -ls /mkdir

重新命名rename

把HDFS中的/mkdir/a重新命名為/mkdir/a2

1)新建檔案src/main/java/Rename.java

2)編譯執行

mvn compile

mvn exec:java -Dexec.mainClass=”Rename” -Dexec.cleanupDaemonThr

eads=false

3)在伺服器中使用HDFS命令驗證

hdfs dfs -ls /mkdir

流方式讀取檔案部分內容

上傳一個文字檔案,然後使用流方式讀取部分內容儲存到當前專案目錄。

1)在伺服器中建立一個測試檔案test.txt,內容:

123456789abcdefghijklmn

上傳到HDFS

hdfs dfs -put test.txt /

2)在本地專案中新建檔案src/main/java/StreamGet.java

2)編譯執行

mvn compile

mvn exec:java -Dexec.mainClass=”StreamGet” -Dexec.cleanupDaemon

Threads=false

3)執行後檢視專案目錄下的test.txt.part2

6789abcdefghijklmn

前面的12345已經被略過

三、深入瞭解

1、寫入機制

向HDFS中寫入檔案時,是按照塊兒為單位的,client會根據配置中設定的塊兒的大小把目標檔案切為多塊,例如檔案是300M ,配置中塊大小值為128M,那麼就分為3塊兒。

具體寫入流程:

  1. client向namenode發請求,說想要上傳檔案
  2. namenode會檢查目標檔案是否存在、父目錄是否存在,檢查沒有問題後返回確認資訊
  3. client再發請求,問第一個block應該傳到哪些datanode上
  4. namenode經過衡量,返回3個可用的datanode(A,B,C)
  5. client與A建立連線,A與B建立連線,B與C建立連線,形成一個pipeline
  6. 傳輸管道建立完成後,client開始向A傳送資料包,此資料包會經過管道一次傳遞到B和C
  7. 當第一個block的資料都傳完以後,client再向namenode請求第二個block上傳到哪些datanode,然後建立傳輸管道傳送資料
  8. 就這樣,直到client把檔案全部上傳完成

2、讀取機制

  1. Client把要讀取的檔案路徑發給namenode,查詢元資料,找到檔案塊所在的datanode伺服器
  2. Client直到了檔案包含哪幾塊兒、每一塊兒在哪些datanode上,就選擇那些離自己進的datanode(在同一機房,如果有多個離著近的,就隨機選擇),請求簡歷socket流
  3. 從datanode獲取資料
  4. Client接收資料包,先本地快取,然後寫入目標檔案
  5. 直到檔案讀取完成

3、NameNode機制

通過對HDFS讀寫流程的瞭解,可以發現namenode是一個很重要的部分,它記錄著整個HDFS系統的元資料,這些元資料是需要持久化的,要儲存到檔案中。

Namenode還要承受巨大的訪問量,client讀寫檔案時都需要請求namenode,寫檔案時要修改元資料,讀檔案時要查詢元資料。

為了提高效率,namenode便將元資料載入到記憶體中,每次修改時,直接修改記憶體,而不是直接修改檔案,同時會記錄下操作日誌,供後期修改檔案時使用。

這樣,namenode對資料的管理就涉及到了3種儲存形式:

  1. 記憶體資料
  2. 元資料檔案
  3. 操作日誌檔案

namenode需要定期對元資料檔案和日誌檔案進行整合,以保證檔案中資料是新的,但這個過程很消耗效能,namenode需要快速地響應client的大量請求,很難去完成檔案整合操作,這時就引入了一個小助手secondnamenode。

secondnamenode會定期從namenode中下載元資料檔案和操作日誌,進行整合,形成新的資料檔案,然後傳回namenode,並替換掉之前的舊檔案。

secondnamenode是namenode的好幫手,替namenode完成了這個重體力活兒,並且還可以作為namenode的一個防災備份,當namenode資料丟失時,secondnamenode上有最近一次整理好的資料檔案,可以傳給namenode進行載入,這樣可以保證最少的資料丟失。

NameNode機制

小結

HDFS的基礎內容介紹完了,希望可以幫助您快速熟悉HDFS的思路和使用方式。如有批評與建議(例如內容有誤、不足的地方、改進建議等),歡迎留言討論。

文章來自微信公眾號:DBAplus社群