Hadoop入門進階課程4--HDFS原理及操做

本文版權歸做者和博客園共有,歡迎轉載,但未經做者贊成必須保留此段聲明,且在文章頁面明顯位置給出原文鏈接,博主爲石山園,博客地址爲 http://www.cnblogs.com/shishanyuan  。該系列課程是應邀實驗樓整理編寫的,這裏須要贊一下實驗樓提供了學習的新方式,能夠邊看博客邊上機實驗,課程地址爲 https://www.shiyanlou.com/courses/237java

【注】該系列所使用到安裝包、測試數據和代碼都可在百度網盤下載,具體地址爲 http://pan.baidu.com/s/10PnDs,下載該PDF文件node

   1環境說明

部署節點操做系統爲CentOS,防火牆和SElinux禁用,建立了一個shiyanlou用戶並在系統根目錄下建立/app目錄,用於存放Hadoop等組件運行包。由於該目錄用於安裝hadoop等組件程序,用戶對shiyanlou必須賦予rwx權限(通常作法是root用戶在根目錄下建立/app目錄,並修改該目錄擁有者爲shiyanlou(chown R shiyanlou:shiyanlou /app)。linux

Hadoop搭建環境:apache

l  虛擬機操做系統: CentOS6.6  64位,單核,1G內存服務器

l  JDK1.7.0_55 64架構

l  Hadoop1.1.2app

 二、HDFS原理

HDFSHadoop Distributed File System)是一個分佈式文件系統,是谷歌的GFS山寨版本。它具備高容錯性並提供了高吞吐量的數據訪問,很是適合大規模數據集上的應用,它提供了一個高度容錯性和高吞吐量的海量數據存儲解決方案。分佈式

l高吞吐量訪問:HDFS的每一個Block分佈在不一樣的Rack上,在用戶訪問時,HDFS會計算使用最近和訪問量最小的服務器給用戶提供。因爲Block在不一樣的Rack上都有備份,因此再也不是單數據訪問,因此速度和效率是很是快的。另外HDFS能夠並行從服務器集羣中讀寫,增長了文件讀寫的訪問帶寬。ide

l高容錯性:系統故障是不可避免的,如何作到故障以後的數據恢復和容錯處理是相當重要的。HDFS經過多方面保證數據的可靠性,多份複製而且分佈到物理位置的不一樣服務器上,數據校驗功能、後臺的連續自檢數據一致性功能都爲高容錯提供了可能。oop

l線性擴展:由於HDFSBlock信息存放到NameNode上,文件的Block分佈到DataNode上,當擴充的時候僅僅添加DataNode數量,系統能夠在不中止服務的狀況下作擴充,不須要人工干預。

2.1HDFS架構

clip_image001[6]

如上圖所示HDFSMasterSlave的結構,分爲NameNodeSecondary NameNodeDataNode三種角色。

lNameNode:在Hadoop1.X中只有一個Master節點,管理HDFS的名稱空間和數據塊映射信息、配置副本策略和處理客戶端請求;

lSecondary NameNode:輔助NameNode,分擔NameNode工做,按期合併fsimagefsedits並推送給NameNode,緊急狀況下可輔助恢復NameNode

lDataNodeSlave節點,實際存儲數據、執行數據塊的讀寫並彙報存儲信息給NameNode

 

2.2HDFS讀操做

clip_image003[6]

1.     客戶端經過調用FileSystem對象的open()方法來打開但願讀取的文件,對於HDFS來講,這個對象時分佈文件系統的一個實例;

2.     DistributedFileSystem經過使用RPC來調用NameNode以肯定文件起始塊的位置,同一Block按照重複數會返回多個位置,這些位置按照Hadoop集羣拓撲結構排序,距離客戶端近的排在前面;

3.     前兩步會返回一個FSDataInputStream對象,該對象會被封裝成DFSInputStream對象,DFSInputStream能夠方便的管理datanodenamenode數據流,客戶端對這個輸入流調用read()方法;

4.     存儲着文件起始塊的DataNode地址的DFSInputStream隨即鏈接距離最近的DataNode,經過對數據流反覆調用read()方法,能夠將數據從DataNode傳輸到客戶端;

5.     到達塊的末端時,DFSInputStream會關閉與該DataNode的鏈接,而後尋找下一個塊的最佳DataNode,這些操做對客戶端來講是透明的,客戶端的角度看來只是讀一個持續不斷的流;

6.     一旦客戶端完成讀取,就對FSDataInputStream調用close()方法關閉文件讀取。

2.3HDFS寫操做

 

clip_image005[6]

1.     客戶端經過調用DistributedFileSystemcreate()方法建立新文件;

2.     DistributedFileSystem經過RPC調用NameNode去建立一個沒有Blocks關聯的新文件,建立前NameNode會作各類校驗,好比文件是否存在、客戶端有無權限去建立等。若是校驗經過,NameNode會爲建立新文件記錄一條記錄,不然就會拋出IO異常;

3.     前兩步結束後會返回FSDataOutputStream的對象,和讀文件的時候類似,FSDataOutputStream被封裝成DFSOutputStreamDFSOutputStream能夠協調NameNodeDatanode。客戶端開始寫數據到DFSOutputStreamDFSOutputStream會把數據切成一個個小的數據包,並寫入內部隊列稱爲「數據隊列」(Data Queue)

4.     DataStreamer會去處理接受Data Queue,它先問詢NameNode這個新的Block最適合存儲的在哪幾個DataNode裏,好比重複數是3,那麼就找到3個最適合的DataNode,把他們排成一個pipeline.DataStreamerPacket按隊列輸出到管道的第一個Datanode中,第一個DataNode又把Packet輸出到第二個DataNode中,以此類推;

5.     DFSOutputStream還有一個對列叫Ack Quene,也是有Packet組成,等待DataNode的收到響應,當Pipeline中的全部DataNode都表示已經收到的時候,這時Akc Quene纔會把對應的Packet包移除掉;

6.     客戶端完成寫數據後調用close()方法關閉寫入流;

7.     DataStreamer把剩餘的包都刷到Pipeline裏而後等待Ack信息,收到最後一個Ack後,通知NameNode把文件標示爲已完成。

2.4HDFS中經常使用到的命令

lhadoop fs

hadoop fs -ls /

hadoop fs -lsr

hadoop fs -mkdir /user/hadoop

hadoop fs -put a.txt /user/hadoop/

hadoop fs -get /user/hadoop/a.txt /

hadoop fs -cp src dst

hadoop fs -mv src dst

hadoop fs -cat /user/hadoop/a.txt

hadoop fs -rm /user/hadoop/a.txt

hadoop fs -rmr /user/hadoop/a.txt

hadoop fs -text /user/hadoop/a.txt

hadoop fs -copyFromLocal localsrc dst hadoop fs -put功能相似。

hadoop fs -moveFromLocal localsrc dst 將本地文件上傳到hdfs,同時刪除本地文件。

lhadoop fsadmin

hadoop dfsadmin -report

hadoop dfsadmin -safemode enter | leave | get | wait

hadoop dfsadmin -setBalancerBandwidth 1000

lhadoop fsck

lstart-balancer.sh

 

相關HDFS API能夠到Apache官網進行查看:

clip_image007[6]

 3測試例子1

3.1測試例子1內容

Hadoop集羣中編譯並運行《權威指南》中的例3.2,讀取HDFS文件內容。

3.2  運行代碼

 1 import java.io.InputStream;
 2 
 3 import java.net.URI;
 4 import org.apache.hadoop.conf.Configuration;
 5 import org.apache.hadoop.fs.*;
 6 import org.apache.hadoop.io.IOUtils;
 7 
 8 public class FileSystemCat {
 9     public static void main(String[] args) throws Exception {
10         String uri = args[0];
11         Configuration conf = new Configuration();
12         FileSystem fs = FileSystem. get(URI.create (uri), conf);
13         InputStream in = null;
14     try {
15             in = fs.open( new Path(uri));
16             IOUtils.copyBytes(in, System.out, 4096, false);
17         } finally {
18             IOUtils.closeStream(in);
19         }
20     }
21 }

 

3.3實現過程

3.3.1建立代碼目錄

使用以下命令啓動Hadoop

cd /app/hadoop-1.1.2/bin

./start-all.sh

/app/hadoop-1.1.2目錄下使用以下命令創建myclassinput目錄:

cd /app/hadoop-1.1.2

mkdir myclass

mkdir input

clip_image009[6]

3.3.2創建例子文件上傳到HDFS

進入/app/hadoop-1.1.2/input目錄,在該目錄中創建quangle.txt文件

cd /app/hadoop-1.1.2/input

touch quangle.txt

vi quangle.txt

內容爲:

On the top of the Crumpetty Tree

The Quangle Wangle sat,

But his face you could not see,

On account of his Beaver Hat.

clip_image011[6]

使用以下命令在hdfs中創建目錄/class4

hadoop fs -mkdir /class4

hadoop fs -ls /

(若是須要直接使用hadoop命令,須要把/app/hadoop-1.1.2加入到Path路徑中)

clip_image013[6]

把例子文件上傳到hdfs/class4文件夾中

cd /app/hadoop-1.1.2/input

hadoop fs -copyFromLocal quangle.txt /class4/quangle.txt

hadoop fs -ls /class4

clip_image015[6]

3.3.3配置本地環境

/app/hadoop-1.1.2/conf目錄中的hadoop-env.sh進行配置,以下如所示:

cd /app/hadoop-1.1.2/conf

sudo vi hadoop-env.sh

加入對HADOOP_CLASPATH變量值,值爲/app/hadoop-1.1.2/myclass,設置完畢後編譯該配置文件,使配置生效

export HADOOP_CLASSPATH=$HADOOP_CLASSPATH:/app/hadoop-1.1.2/myclass

clip_image017[6]

3.3.4編寫代碼

進入/app/hadoop-1.1.2/myclass目錄,在該目錄中創建FileSystemCat.java代碼文件,命令以下:

cd /app/hadoop-1.1.2/myclass/

vi FileSystemCat.java

輸入代碼內容:

clip_image019[6]

3.3.5編譯代碼

/app/hadoop-1.1.2/myclass目錄中,使用以下命令編譯代碼:

javac -classpath ../hadoop-core-1.1.2.jar FileSystemCat.java

ls

clip_image021[6]

3.3.6使用編譯代碼讀取HDFS文件

使用以下命令讀取HDFS/class4/quangle.txt內容:

hadoop FileSystemCat /class4/quangle.txt

clip_image023[6]

 4測試例子2

4.1測試例子2內容

在本地文件系統生成一個大約100字節的文本文件,寫一段程序讀入這個文件並將其第101-120字節的內容寫入HDFS成爲一個新文件。

4.2運行代碼

注意:在編譯前請先刪除中文註釋!

 1 import java.io.File;
 2 import java.io.FileInputStream;
 3 import java.io.FileOutputStream;
 4 import java.io.OutputStream;
 5 import java.net.URI;
 6 
 7 import org.apache.hadoop.conf.Configuration;
 8 import org.apache.hadoop.fs.FSDataInputStream;
 9 import org.apache.hadoop.fs.FileSystem;
10 import org.apache.hadoop.fs.Path;
11 import org.apache.hadoop.io.IOUtils;
12 import org.apache.hadoop.util.Progressable;
13 
14 public class LocalFile2Hdfs {
15     public static void main(String[] args) throws Exception {
16 
17         // 獲取讀取源文件和目標文件位置參數
18         String local = args[0];
19         String uri = args[1];
20         
21         FileInputStream in = null;
22         OutputStream out = null;
23         Configuration conf = new Configuration();
24         try {
25             // 獲取讀入文件數據
26             in = new FileInputStream(new File(local));
27 
28             // 獲取目標文件信息
29             FileSystem fs = FileSystem.get(URI.create(uri), conf);
30             out = fs.create(new Path(uri), new Progressable() {
31                 @Override
32                 public void progress() {
33                     System.out.println("*");
34                 }
35             });
36 
37             // 跳過前100個字符
38             in.skip(100);
39             byte[] buffer = new byte[20];
40                 
41             // 從101的位置讀取20個字符到buffer中
42             int bytesRead = in.read(buffer);
43             if (bytesRead >= 0) {
44                 out.write(buffer, 0, bytesRead);
45             }
46         } finally {
47             IOUtils.closeStream(in);
48             IOUtils.closeStream(out);
49         }        
50     }

 

4.3實現過程

4.3.1編寫代碼

進入/app/hadoop-1.1.2/myclass目錄,在該目錄中創建LocalFile2Hdfs.java代碼文件,命令以下:

cd /app/hadoop-1.1.2/myclass/

vi LocalFile2Hdfs.java

輸入代碼內容:

clip_image025[6]

4.3.2編譯代碼

/app/hadoop-1.1.2/myclass目錄中,使用以下命令編譯代碼:

javac -classpath ../hadoop-core-1.1.2.jar LocalFile2Hdfs.java

clip_image027[6]

4.3.3創建測試文件

進入/app/hadoop-1.1.2/input目錄,在該目錄中創建local2hdfs.txt文件

cd /app/hadoop-1.1.2/input/

vi local2hdfs.txt

內容爲:

Washington (CNN) -- Twitter is suing the U.S. government in an effort to loosen restrictions on what the social media giant can say publicly about the national security-related requests it receives for user data.

The company filed a lawsuit against the Justice Department on Monday in a federal court in northern California, arguing that its First Amendment rights are being violated by restrictions that forbid the disclosure of how many national security letters and Foreign Intelligence Surveillance Act court orders it receives -- even if that number is zero.

Twitter vice president Ben Lee wrote in a blog post that it's suing in an effort to publish the full version of a "transparency report" prepared this year that includes those details.

The San Francisco-based firm was unsatisfied with the Justice Department's move in January to allow technological firms to disclose the number of national security-related requests they receive in broad ranges.

clip_image029[6]

4.3.4使用編譯代碼上傳文件內容到HDFS

使用以下命令讀取local2hdfs101-120字節的內容寫入HDFS成爲一個新文件:

cd /app/hadoop-1.1.2/input

hadoop LocalFile2Hdfs local2hdfs.txt /class4/local2hdfs_part.txt

clip_image031[6]

4.3.5驗證是否成功

使用以下命令讀取local2hdfs_part.txt內容:

hadoop fs -cat /class4/local2hdfs_part.txt

clip_image033[6]

 5測試例子3

5.1測試例子3內容

測試例子2的反向操做,在HDFS中生成一個大約100字節的文本文件,寫一段程序讀入這個文件,並將其第101-120字節的內容寫入本地文件系統成爲一個新文件。

5.2程序代碼

 1 import java.io.File;
 2 import java.io.FileInputStream;
 3 import java.io.FileOutputStream;
 4 import java.io.OutputStream;
 5 import java.net.URI;
 6 
 7 import org.apache.hadoop.conf.Configuration;
 8 import org.apache.hadoop.fs.FSDataInputStream;
 9 import org.apache.hadoop.fs.FileSystem;
10 import org.apache.hadoop.fs.Path;
11 import org.apache.hadoop.io.IOUtils;
12 
13 public class Hdfs2LocalFile {
14     public static void main(String[] args) throws Exception {
15 
16         String uri = args[0];
17         String local = args[1];
18         
19         FSDataInputStream in = null;
20         OutputStream out = null;
21         Configuration conf = new Configuration();
22         try {
23             FileSystem fs = FileSystem.get(URI.create(uri), conf);
24             in = fs.open(new Path(uri));
25             out = new FileOutputStream(local);
26 
27             byte[] buffer = new byte[20];
28             in.skip(100);
29             int bytesRead = in.read(buffer);
30             if (bytesRead >= 0) {
31                 out.write(buffer, 0, bytesRead);
32             }
33         } finally {
34             IOUtils.closeStream(in);
35             IOUtils.closeStream(out);
36         }    
37     }
38 }

5.3實現過程

5.3.1編寫代碼

進入/app/hadoop-1.1.2/myclass目錄,在該目錄中創建Hdfs2LocalFile.java代碼文件,命令以下:

cd /app/hadoop-1.1.2/myclass/

vi Hdfs2LocalFile.java

輸入代碼內容:

clip_image035[6]

5.3.2編譯代碼

/app/hadoop-1.1.2/myclass目錄中,使用以下命令編譯代碼:

javac -classpath ../hadoop-core-1.1.2.jar Hdfs2LocalFile.java

clip_image037[6]

5.3.3創建測試文件

進入/app/hadoop-1.1.2/input目錄,在該目錄中創建hdfs2local.txt文件

cd /app/hadoop-1.1.2/input/

vi hdfs2local.txt

內容爲:

The San Francisco-based firm was unsatisfied with the Justice Department's move in January to allow technological firms to disclose the number of national security-related requests they receive in broad ranges.

"It's our belief that we are entitled under the First Amendment to respond to our users' concerns and to the statements of U.S. government officials by providing information about the scope of U.S. government surveillance -- including what types of legal process have not been received," Lee wrote. "We should be free to do this in a meaningful way, rather than in broad, inexact ranges."

clip_image039[6]

/app/hadoop-1.1.2/input目錄下把該文件上傳到hdfs/class4/文件夾中

hadoop fs -copyFromLocal hdfs2local.txt /class4/hdfs2local.txt

hadoop fs -ls /class4/

clip_image041[6]

5.3.4使用編譯代碼把文件內容從HDFS輸出到文件系統中

使用以下命令讀取hdfs2local.txt101-120字節的內容寫入本地文件系統成爲一個新文件:

hadoop Hdfs2LocalFile /class4/hdfs2local.txt hdfs2local_part.txt

clip_image043[6]

5.3.5驗證是否成功

使用以下命令讀取hdfs2local_part.txt內容:

cat hdfs2local_part.txt

clip_image045[6]

相關文章
相關標籤/搜索