天天看點

HDFS(上):HDFS優缺點、HDFS操作、HDFS用戶端操作、HDFS的API、HDFS資料流、HDFS的IO流、HDFS讀寫資料流程、HDFS檔案處理詳解、windows安裝hadoop

視訊資料來源于尚矽谷

HDFS(上)目錄

第1章·HDFS概述

1.1 HDFS産出背景及定義

1.2·HDFS優缺點

1.3·HDFS 組成架構

1.4 HDFS 檔案塊太小(面試重點)

第2章·HDFS的Shell操作(開發重點)

第3章·HDFS用戶端操作(開發重點)

3.1·HDFS 用戶端環境準備

3.2·HDFS的API操作。

3.2.1HDFS檔案上傳(測試參數優先級)

3.2.2·HDFS檔案下載下傳

3.2.3·HDFS檔案夾删除。

3.2.4-HDFS檔案名更改。

3.2.5HDFS檔案詳情檢視

3.2.6·HDFS檔案和檔案夾判斷。

API操作筆記完整代碼

3.3·HDFS的I/O流操作(擴充)

3.3.1HDFS檔案上傳

3.3.2HDFS檔案下載下傳

3.3.3·定位檔案讀取。

第4章·HDFS的資料流(面試重點)。

4.1·HDFS 寫資料流程

4.1.1.剖析檔案寫入

4.1.2.網絡拓撲-節點距離計算

4.1.3·機架感覺(副本存儲節點選擇)

4.2·HDFS 讀資料流程

第1章 HDFS概述

1.1 HDFS産出背景及定義

HDFS産生背景

随着資料量越來越大,在一個作業系統存不下所有的資料,那麼就配置設定到更多的作業系統管理的磁盤中,但是不友善管理和維護,迫切需要一種系統來管理多台機器上的檔案,這就是分布式檔案管理系統。HDFS隻是分布式檔案管理系統中的一種。

1.2HDFS定義

HDFS(Hadoop Distributed File System),它是一個檔案系統,用于存儲檔案,通過目錄樹來定位檔案;其次,它是分布式的,由很多伺服器聯合起來實作其功能,叢集中的伺服器有各自的角色。

HDFS的使用場景:适合一次寫入,多次讀出的場累,且不支援檔案的修改。适合用來做資料分析,并不适合用來做網盤應用。

HDFS優缺點

HDFS(上):HDFS優缺點、HDFS操作、HDFS用戶端操作、HDFS的API、HDFS資料流、HDFS的IO流、HDFS讀寫資料流程、HDFS檔案處理詳解、windows安裝hadoop
HDFS(上):HDFS優缺點、HDFS操作、HDFS用戶端操作、HDFS的API、HDFS資料流、HDFS的IO流、HDFS讀寫資料流程、HDFS檔案處理詳解、windows安裝hadoop

1.3 HDFS組成架構

1)NameNode(nn):就是Master,它是一個主管、管理者。

(1)管理HDFS的名稱空間;

(2)配置副本政策;

(3)管理資料塊(Block)映射資訊;

(4)處理用戶端讀寫請求。

2)DataNode:就是Slave。NameN ode下達指令,DataNode執行實際的操作。

(1)存儲實際的資料塊;

(2)執行資料塊的讀/寫操作。

HDFS(上):HDFS優缺點、HDFS操作、HDFS用戶端操作、HDFS的API、HDFS資料流、HDFS的IO流、HDFS讀寫資料流程、HDFS檔案處理詳解、windows安裝hadoop

3)Client:就是用戶端。

(1)檔案切分。檔案上傳IDFS的時候,Client将檔案切分成一個一個的Block,然後進行上傳;

(2)與NameNode互動,取檔案的位置資訊;

(3)與DataNode互動,讀取或者寫入資料;

(4)Client是供一些指令來管理HDFS,比如Narme Node格式化;

(5)Client可以通過一些指令來訪可HDFS,比如對HDFS增删查改操作;

4)Secondary NameNode:并非NameNode的熱備。當NameNode挂掉的時候,它并不能馬上替換NameNode并提供服務。

(1)輔助NarmeNode,分擔其工作量,比如定期合并Fsirmage和Edits,并推送給NameNode;

(2)在緊急情況下,可輔助恢複NameNode。

1.4 HDFS檔案塊大小(面試重點)

HDFS中的檔案在實體上是分塊存儲(Block),塊的大小可以通過配置參數(dfs.blocksize)來規定,預設大小在Hadoop2.x版本中是128M,老版本中是64M。

HDFS(上):HDFS優缺點、HDFS操作、HDFS用戶端操作、HDFS的API、HDFS資料流、HDFS的IO流、HDFS讀寫資料流程、HDFS檔案處理詳解、windows安裝hadoop

思考:為什麼塊的大小不能設定太小,也不能設定太大?

(1)HDFS的塊設定太小,會增加尋址時間,程式一直在找塊的開始位置;

(2)如果塊設定的太大,從磁盤傳輸資料的時間會明顯大于定位這個塊開始位置所需的時間。導緻程式在處理這塊資料時,會非常慢。

總結:HDFS塊的大小設定主要取決于磁盤傳輸速率。

第2章 HDFS的Shell操作(開發重點)

1.基本文法

bin/hadoop fs 具體指令 OR bin/hdfs dfs 具體指令

dfs是fs的實作類。

2.指令大全

[[email protected] hadoop-2.7.2]$ bin/hadoop fs

[-appendToFile <localsrc> ... <dst>]
    [-cat [-ignoreCrc] <src> ...]
    [-checksum <src> ...]
    [-chgrp [-R] GROUP PATH...]
    [-chmod [-R] <MODE[,MODE]... | OCTALMODE> PATH...]
    [-chown [-R] [OWNER][:[GROUP]] PATH...]
    [-copyFromLocal [-f] [-p] <localsrc> ... <dst>]
    [-copyToLocal [-p] [-ignoreCrc] [-crc] <src> ... <localdst>]
    [-count [-q] <path> ...]
    [-cp [-f] [-p] <src> ... <dst>]
    [-createSnapshot <snapshotDir> [<snapshotName>]]
    [-deleteSnapshot <snapshotDir> <snapshotName>]
    [-df [-h] [<path> ...]]
    [-du [-s] [-h] <path> ...]
    [-expunge]
    [-get [-p] [-ignoreCrc] [-crc] <src> ... <localdst>]
    [-getfacl [-R] <path>]
    [-getmerge [-nl] <src> <localdst>]
    [-help [cmd ...]]
    [-ls [-d] [-h] [-R] [<path> ...]]
    [-mkdir [-p] <path> ...]
    [-moveFromLocal <localsrc> ... <dst>]
    [-moveToLocal <src> <localdst>]
    [-mv <src> ... <dst>]
    [-put [-f] [-p] <localsrc> ... <dst>]
    [-renameSnapshot <snapshotDir> <oldName> <newName>]
    [-rm [-f] [-r|-R] [-skipTrash] <src> ...]
    [-rmdir [--ignore-fail-on-non-empty] <dir> ...]
    [-setfacl [-R] [{-b|-k} {-m|-x <acl_spec>} <path>]|[--set <acl_spec> <path>]]
    [-setrep [-R] [-w] <rep> <path> ...]
    [-stat [format] <path> ...]
    [-tail [-f] <file>]
    [-test -[defsz] <path>]
    [-text [-ignoreCrc] <src> ...]
    [-touchz <path> ...]
    [-usage [cmd ...]]
           

3.常用指令實操

(0)啟動Hadoop叢集(友善後續的測試)

[[email protected] hadoop-2.7.2]$ sbin/start-dfs.sh
[[email protected] hadoop-2.7.2]$ sbin/start-yarn.sh
           

(1)-help:輸出這個指令參數

[[email protected] hadoop-2.7.2]$ hadoop fs -help rm
           
HDFS(上):HDFS優缺點、HDFS操作、HDFS用戶端操作、HDFS的API、HDFS資料流、HDFS的IO流、HDFS讀寫資料流程、HDFS檔案處理詳解、windows安裝hadoop

(2)-ls: 顯示目錄資訊

[[email protected] hadoop-2.7.2]$ hadoop fs -ls /
           
HDFS(上):HDFS優缺點、HDFS操作、HDFS用戶端操作、HDFS的API、HDFS資料流、HDFS的IO流、HDFS讀寫資料流程、HDFS檔案處理詳解、windows安裝hadoop

(3)-mkdir:在HDFS上建立目錄(-p表示遞歸建立檔案夾)

[atgui[email protected] hadoop-2.7.2]$ hadoop fs -mkdir -p 	/sanguo/shuguo
           

(4)-moveFromLocal:從本地剪切粘貼到HDFS

[[email protected] hadoop-2.7.2]$ touch kongming.txt
[[email protected] hadoop-2.7.2]$ hadoop fs  -moveFromLocal  ./kongming.txt  /sanguo/shuguo
           

浏覽器檢視http://hadoop102:50070

(5)-appendToFile:追加一個檔案到已經存在的檔案末尾

[[email protected] hadoop-2.7.2]$ touch liubei.txt
[[email protected] hadoop-2.7.2]$ vi liubei.txt
           

輸入

san gu mao lu
[[email protected] hadoop-2.7.2]$ hadoop fs -appendToFile liubei.txt /sanguo/shuguo/kongming.txt
           

踩過的坑1:報Failed to replace a bad datanode on the existing pipeline due to no more good datanodes being available to try.異常。

HDFS(上):HDFS優缺點、HDFS操作、HDFS用戶端操作、HDFS的API、HDFS資料流、HDFS的IO流、HDFS讀寫資料流程、HDFS檔案處理詳解、windows安裝hadoop

hadoop官網說明錯誤原因If there is a datanode/network failure in the write pipeline, DFSClient will try to remove the failed datanode from the pipeline and then continue writing with the remaining datanodes. As a result, the number of datanodes in the pipeline is decreased. The feature is to add new datanodes to the pipeline. This is a site-wide property to enable/disable the feature. When the cluster size is extremely small, e.g. 3 nodes or less, cluster administrators may want to set the policy to NEVER in the default configuration file or disable this feature. Otherwise, users may experience an unusually high rate of pipeline failures since it is impossible to find new datanodes for replacement. See also dfs.client.block.write.replace-datanode-on-failure.

解決方法:在hadoop安裝目錄下etc/Hadoop/hdfs-site.xml中添加配置

<!--解決Failed to replace a bad datanode on the existing pipeline due to no more good datanodes being availa 異常 -->
<property>
  <name>dfs.client.block.write.replace-datanode-on-failure.enable</name>
  <value>true</value>
</property>
<property>
  <name>dfs.client.block.write.replace-datanode-on-failure.policy</name>
  <value>NEVER</value>
</property>
           

踩過的坑2:報appendToFile: Failed to APPEND_FILE /sanguo/shuguo/zgl for DFSClient_NONMAPREDUCE_-94021698_1 on 192.168.1.102 because lease recovery is in progress. Try again later.異常

解決方法:給檔案增加寫入權限即可

HDFS(上):HDFS優缺點、HDFS操作、HDFS用戶端操作、HDFS的API、HDFS資料流、HDFS的IO流、HDFS讀寫資料流程、HDFS檔案處理詳解、windows安裝hadoop

(6)-cat:顯示檔案内容

[[email protected] hadoop-2.7.2]$ hadoop fs -cat /sanguo/shuguo/kongming.txt
           
HDFS(上):HDFS優缺點、HDFS操作、HDFS用戶端操作、HDFS的API、HDFS資料流、HDFS的IO流、HDFS讀寫資料流程、HDFS檔案處理詳解、windows安裝hadoop

(7)-chgrp 、-chmod、-chown:Linux檔案系統中的用法一樣,修改檔案所屬權限

[[email protected] hadoop-2.7.2]$ hadoop fs  -chmod  666  /sanguo/shuguo/kongming.txt
[[email protected] hadoop-2.7.2]$ hadoop fs  -chown  atguigu:atguigu   /sanguo/shuguo/kongming.txt
           
HDFS(上):HDFS優缺點、HDFS操作、HDFS用戶端操作、HDFS的API、HDFS資料流、HDFS的IO流、HDFS讀寫資料流程、HDFS檔案處理詳解、windows安裝hadoop

将檔案所屬權限改為root

HDFS(上):HDFS優缺點、HDFS操作、HDFS用戶端操作、HDFS的API、HDFS資料流、HDFS的IO流、HDFS讀寫資料流程、HDFS檔案處理詳解、windows安裝hadoop

(8)-copyFromLocal:從本地檔案系統中拷貝檔案到HDFS路徑去

[atguigu@hadoop102 hadoop-2.7.2]$ hadoop fs -copyFromLocal README.txt /
           
HDFS(上):HDFS優缺點、HDFS操作、HDFS用戶端操作、HDFS的API、HDFS資料流、HDFS的IO流、HDFS讀寫資料流程、HDFS檔案處理詳解、windows安裝hadoop

(9)-copyToLocal:從HDFS拷貝到本地

[[email protected] hadoop-2.7.2]$ hadoop fs -copyToLocal /sanguo/shuguo/kongming.txt ./
           
HDFS(上):HDFS優缺點、HDFS操作、HDFS用戶端操作、HDFS的API、HDFS資料流、HDFS的IO流、HDFS讀寫資料流程、HDFS檔案處理詳解、windows安裝hadoop

(10)-cp :從HDFS的一個路徑拷貝到HDFS的另一個路徑

[[email protected] hadoop-2.7.2]$ hadoop fs -cp /sanguo/shuguo/kongming.txt /zhuge.txt
           

(11)-mv:在HDFS目錄中移動檔案

[[email protected] hadoop-2.7.2]$ hadoop fs -mv /zhuge.txt /sanguo/shuguo/
           

(12)-get:等同于copyToLocal,就是從HDFS下載下傳檔案到本地

[[email protected] hadoop-2.7.2]$ hadoop fs -get /sanguo/shuguo/kongming.txt ./
           

(13)-getmerge:合并下載下傳多個檔案,比如HDFS的目錄 /user/atguigu/test下有多個檔案:log.1, log.2,log.3,…

[[email protected] hadoop-2.7.2]$ hadoop fs -getmerge /user/atguigu/test/* ./zaiyiqi.txt
           
HDFS(上):HDFS優缺點、HDFS操作、HDFS用戶端操作、HDFS的API、HDFS資料流、HDFS的IO流、HDFS讀寫資料流程、HDFS檔案處理詳解、windows安裝hadoop

(14)-put:等同于copyFromLocal

[[email protected] hadoop-2.7.2]$ hadoop fs -put ./zaiyiqi.txt /user/atguigu/test/
           

(15)-tail:顯示一個檔案的末尾

[[email protected] hadoop-2.7.2]$ hadoop fs -tail /sanguo/shuguo/kongming.txt
           

(16)-rm:删除檔案或檔案夾

[[email protected] hadoop-2.7.2]$ hadoop fs -rm /user/atguigu/test/jinlian2.txt
           

拓展:遞歸删除檔案夾:-rmr指令

[[email protected] wcinput]$ hadoop fs -rmr  /java
           

(17)-rmdir:删除空目錄

[[email protected] hadoop-2.7.2]$ hadoop fs -mkdir /test
[[email protected] hadoop-2.7.2]$ hadoop fs -rmdir /test
           

(18)-du統計檔案夾的大小資訊

[[email protected] hadoop-2.7.2]$ hadoop fs -du -s -h /user/atguigu/test
2.7 K  /user/atguigu/test

[[email protected] hadoop-2.7.2]$ hadoop fs -du  -h /user/atguigu/test
1.3 K  /user/atguigu/test/README.txt
15     /user/atguigu/test/jinlian.txt
1.4 K  /user/atguigu/test/zaiyiqi.txt
           
HDFS(上):HDFS優缺點、HDFS操作、HDFS用戶端操作、HDFS的API、HDFS資料流、HDFS的IO流、HDFS讀寫資料流程、HDFS檔案處理詳解、windows安裝hadoop

(19)-setrep:設定HDFS中檔案的副本數量

[[email protected] hadoop-2.7.2]$ hadoop fs -setrep 10 /sanguo/shuguo/kongming.txt
           
HDFS(上):HDFS優缺點、HDFS操作、HDFS用戶端操作、HDFS的API、HDFS資料流、HDFS的IO流、HDFS讀寫資料流程、HDFS檔案處理詳解、windows安裝hadoop

圖3-3 HDFS副本數量

這裡設定的副本數隻是記錄在NameNode的中繼資料中,是否真的會有這麼多副本,還得看DataNode的數量。因為目前隻有3台裝置,最多也就3個副本,隻有節點數的增加到10台時,副本數才能達到10。

第3章 HDFS用戶端操作(開發重點)

3.1 HDFS用戶端環境準備

1.根據自己電腦的作業系統拷貝對應的編譯後的hadoop jar包到非中文路徑(例如:D:\Develop\hadoop-2.7.2),如圖3-4所示。

HDFS(上):HDFS優缺點、HDFS操作、HDFS用戶端操作、HDFS的API、HDFS資料流、HDFS的IO流、HDFS讀寫資料流程、HDFS檔案處理詳解、windows安裝hadoop

圖3-4 編譯後的hadoop jar包

2.配置HADOOP_HOME環境變量,如圖3-5所示。

HDFS(上):HDFS優缺點、HDFS操作、HDFS用戶端操作、HDFS的API、HDFS資料流、HDFS的IO流、HDFS讀寫資料流程、HDFS檔案處理詳解、windows安裝hadoop

Win10配置方法

HDFS(上):HDFS優缺點、HDFS操作、HDFS用戶端操作、HDFS的API、HDFS資料流、HDFS的IO流、HDFS讀寫資料流程、HDFS檔案處理詳解、windows安裝hadoop

圖3-5 配置HADOOP_HOME環境變量

3.配置Path環境變量,如圖3-6所示。

HDFS(上):HDFS優缺點、HDFS操作、HDFS用戶端操作、HDFS的API、HDFS資料流、HDFS的IO流、HDFS讀寫資料流程、HDFS檔案處理詳解、windows安裝hadoop

圖3-6 配置Path環境變量

通過cmd指令指令檢查安裝情況

HDFS(上):HDFS優缺點、HDFS操作、HDFS用戶端操作、HDFS的API、HDFS資料流、HDFS的IO流、HDFS讀寫資料流程、HDFS檔案處理詳解、windows安裝hadoop

4.建立一個Maven工程HdfsClientDemo

5.導入相應的依賴坐标+日志添加

<dependencies>
		<dependency>
			<groupId>junit</groupId>
			<artifactId>junit</artifactId>
			<version>RELEASE</version>
		</dependency>
		<dependency>
			<groupId>org.apache.logging.log4j</groupId>
			<artifactId>log4j-core</artifactId>
			<version>2.8.2</version>
		</dependency>
		<dependency>
			<groupId>org.apache.hadoop</groupId>
			<artifactId>hadoop-common</artifactId>
			<version>2.7.2</version>
		</dependency>
		<dependency>
			<groupId>org.apache.hadoop</groupId>
			<artifactId>hadoop-client</artifactId>
			<version>2.7.2</version>
		</dependency>
		<dependency>
			<groupId>org.apache.hadoop</groupId>
			<artifactId>hadoop-hdfs</artifactId>
			<version>2.7.2</version>
		</dependency>
		<dependency>
			<groupId>jdk.tools</groupId>
			<artifactId>jdk.tools</artifactId>
			<version>1.8</version>
			<scope>system</scope>
			<systemPath>${JAVA_HOME}/lib/tools.jar</systemPath>
		</dependency>
</dependencies>
           

執行導入jar包

HDFS(上):HDFS優缺點、HDFS操作、HDFS用戶端操作、HDFS的API、HDFS資料流、HDFS的IO流、HDFS讀寫資料流程、HDFS檔案處理詳解、windows安裝hadoop

注意:如果Eclipse/Idea列印不出日志,在控制台上隻顯示

1.log4j:WARN No appenders could be found for logger (org.apache.hadoop.util.Shell).  
2.log4j:WARN Please initialize the log4j system properly.  
3.log4j:WARN See http://logging.apache.org/log4j/1.2/faq.html#noconfig for more info.
           

需要在項目的src/main/resources目錄下,建立一個檔案,命名為“log4j.properties”,在檔案中填入

log4j.rootLogger=INFO, stdout
log4j.appender.stdout=org.apache.log4j.ConsoleAppender
log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
log4j.appender.stdout.layout.ConversionPattern=%d %p [%c] - %m%n
log4j.appender.logfile=org.apache.log4j.FileAppender
log4j.appender.logfile.File=target/spring.log
log4j.appender.logfile.layout=org.apache.log4j.PatternLayout
log4j.appender.logfile.layout.ConversionPattern=%d %p [%c] - %m%n
           
HDFS(上):HDFS優缺點、HDFS操作、HDFS用戶端操作、HDFS的API、HDFS資料流、HDFS的IO流、HDFS讀寫資料流程、HDFS檔案處理詳解、windows安裝hadoop

6.建立包名:com.atguigu.hdfs

測試代碼

public class HDFSClient {
    @Test
    public void put() throws IOException, InterruptedException {
        FileSystem fileSystem = FileSystem.get(URI.create("hdfs://hadoop102:9000"), new Configuration(), "atguigu");
        fileSystem.copyFromLocalFile(new Path("D:\\Workspaces\\Java20190715\\hdfs20190817\\src\\main\\java\\Files\\1.txt"),
                new Path("/wcoutput"));
        fileSystem.close();
        System.out.println("測試上傳成功");
    }
}
           
HDFS(上):HDFS優缺點、HDFS操作、HDFS用戶端操作、HDFS的API、HDFS資料流、HDFS的IO流、HDFS讀寫資料流程、HDFS檔案處理詳解、windows安裝hadoop

7.建立HdfsClient類

public class HdfsClient{	
@Test
public void testMkdirs() throws IOException, InterruptedException, URISyntaxException{
		
		// 1 擷取檔案系統
		Configuration configuration = new Configuration();
		// 配置在叢集上運作
		// configuration.set("fs.defaultFS", "hdfs://hadoop102:9000");
		// FileSystem fs = FileSystem.get(configuration);

		FileSystem fs = FileSystem.get(new URI("hdfs://hadoop102:9000"), configuration, "atguigu");
		
		// 2 建立目錄
		fs.mkdirs(new Path("/1108/daxian/banzhang"));
		
		// 3 關閉資源
		fs.close();
	}
}
           

8.執行程式

運作時需要配置使用者名稱,如圖3-7所示

HDFS(上):HDFS優缺點、HDFS操作、HDFS用戶端操作、HDFS的API、HDFS資料流、HDFS的IO流、HDFS讀寫資料流程、HDFS檔案處理詳解、windows安裝hadoop

圖3-7 配置使用者名稱

用戶端去操作HDFS時,是有一個使用者身份的。預設情況下,HDFS用戶端API會從JVM中擷取一個參數來作為自己的使用者身份:-DHADOOP_USER_NAME=atguigu,atguigu為使用者名稱。

3.2 HDFS的API操作

3.2.1 HDFS檔案上傳(測試參數優先級)

1.編寫源代碼

@Test
public void testCopyFromLocalFile() throws IOException, InterruptedException, URISyntaxException {
// 1 擷取檔案系統
	Configuration configuration = new Configuration();
	configuration.set("dfs.replication", "2");
	FileSystem fs = FileSystem.get(new URI("hdfs://hadoop102:9000"), configuration, "atguigu");
	// 2 上傳檔案
	fs.copyFromLocalFile(new Path("e:/banzhang.txt"), new Path("/banzhang.txt"));
	// 3 關閉資源
	fs.close();
	System.out.println("over");
}
           

2.将hdfs-site.xml拷貝到項目的根目錄下

<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet type="text/xsl" href="configuration.xsl" target="_blank" rel="external nofollow" ?>

<configuration>
	<property>
		<name>dfs.replication</name>
        <value>1</value>
	</property>
</configuration>
           

3.參數優先級

參數優先級排序:(1)用戶端代碼中設定的值 >(2)ClassPath下的使用者自定義配置檔案 >(3)然後是伺服器的預設配置

3.2.2 HDFS檔案下載下傳

@Test
public void testCopyToLocalFile() throws IOException, InterruptedException, URISyntaxException{

		// 1 擷取檔案系統
		Configuration configuration = new Configuration();
		FileSystem fs = FileSystem.get(new URI("hdfs://hadoop102:9000"), configuration, "atguigu");
		
		// 2 執行下載下傳操作
		// boolean delSrc 指是否将原檔案删除
		// Path src 指要下載下傳的檔案路徑
		// Path dst 指将檔案下載下傳到的路徑
		// boolean useRawLocalFileSystem 是否開啟檔案校驗
		fs.copyToLocalFile(false, new Path("/banzhang.txt"), new Path("e:/banhua.txt"), true);
		
		// 3 關閉資源
		fs.close();
}
           

3.2.3 HDFS檔案夾删除

@Test
public void testDelete() throws IOException, InterruptedException, URISyntaxException{

	// 1 擷取檔案系統
	Configuration configuration = new Configuration();
	FileSystem fs = FileSystem.get(new URI("hdfs://hadoop102:9000"), configuration, "atguigu");
		
	// 2 執行删除
	fs.delete(new Path("/0508/"), true);
		
	// 3 關閉資源
	fs.close();
}
           

3.2.4 HDFS檔案名更改

@Test
public void testRename() throws IOException, InterruptedException, URISyntaxException{

	// 1 擷取檔案系統
	Configuration configuration = new Configuration();
	FileSystem fs = FileSystem.get(new URI("hdfs://hadoop102:9000"), configuration, "atguigu"); 
		
	// 2 修改檔案名稱
	fs.rename(new Path("/banzhang.txt"), new Path("/banhua.txt"));
		
	// 3 關閉資源
	fs.close();
}
           

3.2.5 HDFS檔案詳情檢視

檢視檔案名稱、權限、長度、塊資訊

@Test
public void testListFiles() throws IOException, InterruptedException, URISyntaxException{

	// 1擷取檔案系統
	Configuration configuration = new Configuration();
	FileSystem fs = FileSystem.get(new URI("hdfs://hadoop102:9000"), configuration, "atguigu"); 
		
	// 2 擷取檔案詳情
	RemoteIterator<LocatedFileStatus> listFiles = fs.listFiles(new Path("/"), true);
		
	while(listFiles.hasNext()){
		LocatedFileStatus status = listFiles.next();
			
		// 輸出詳情
		// 檔案名稱
		System.out.println(status.getPath().getName());
		// 長度
		System.out.println(status.getLen());
		// 權限
		System.out.println(status.getPermission());
		// 分組
		System.out.println(status.getGroup());
			
		// 擷取存儲的塊資訊
		BlockLocation[] blockLocations = status.getBlockLocations();
			
		for (BlockLocation blockLocation : blockLocations) {
				
			// 擷取塊存儲的主機節點
			String[] hosts = blockLocation.getHosts();
				
			for (String host : hosts) {
				System.out.println(host);
			}
		}
		System.out.println("-----------班長的分割線----------");
	}
// 3 關閉資源
fs.close();
}
           

3.2.6 HDFS檔案和檔案夾判斷

@Test
public void testListStatus() throws IOException, InterruptedException, URISyntaxException{
		
	// 1 擷取檔案配置資訊
	Configuration configuration = new Configuration();
	FileSystem fs = FileSystem.get(new URI("hdfs://hadoop102:9000"), configuration, "atguigu");
		
	// 2 判斷是檔案還是檔案夾
	FileStatus[] listStatus = fs.listStatus(new Path("/"));
		
	for (FileStatus fileStatus : listStatus) {
		
		// 如果是檔案
		if (fileStatus.isFile()) {
				System.out.println("f:"+fileStatus.getPath().getName());
			}else {
				System.out.println("d:"+fileStatus.getPath().getName());
			}
		}
		
	// 3 關閉資源
	fs.close();
}
           

API操作筆記完整代碼

import org.apache.hadoop.conf.Configuration;
import org.apache.hadoop.fs.*;
import org.apache.hadoop.io.IOUtils;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;

import java.io.*;
import java.net.URI;
/**
 * @author 黃佳豪
 * @create 2019-08-17-17:36
 * 注:由于使用@Test單元測試時用本地檔案相對路徑會出問題,以下全部使用絕對路徑
 * 使用main方法則不會出現該問題。
 */
public class HdfsClientTest {
static FileSystem fs;
static Configuration configuration;

/**
 * 第一步:建立對象
 *
 * @throws IOException
 * @throws InterruptedException
 */
@Before
public void before() throws IOException, InterruptedException {
    configuration = new Configuration();
    fs = FileSystem.get(URI.create("hdfs://hadoop102:9000"), configuration, "atguigu");
}

    /**
     * 最後一步:關閉資源
     *
     * @throws IOException
     * @throws InterruptedException
     */
    @After
    public void after() throws IOException, InterruptedException {
        System.out.println("程式執行完畢且沒報錯,關閉資源");
        fs.close();
    }

    /**
     * 測試連接配接并下載下傳檔案,由于隻有copyToLocalFile而沒有get方法,
     * 故用shell操作HDFS時建議使用-copyToLocal代替-get
     * @throws IOException
     */
    @Test
    public void TestConn() throws IOException {
        fs.copyToLocalFile(new Path("/sanguo/shuguo/lb"), new Path("hdfs20190817\\src\\main\\java\\Files\\lb.txt"));
    }
           
HDFS(上):HDFS優缺點、HDFS操作、HDFS用戶端操作、HDFS的API、HDFS資料流、HDFS的IO流、HDFS讀寫資料流程、HDFS檔案處理詳解、windows安裝hadoop
/**
 * 建立目錄
 * @throws IOException
 */
@Test
public void mkdir() throws IOException {
    fs.mkdirs(new Path("/HDFSClientTest"));
}
           
HDFS(上):HDFS優缺點、HDFS操作、HDFS用戶端操作、HDFS的API、HDFS資料流、HDFS的IO流、HDFS讀寫資料流程、HDFS檔案處理詳解、windows安裝hadoop
/**
 * 上傳檔案
 * copyFromLocalFile中的src:本地檔案路徑,dst:Hdfs檔案路徑
 * @throws IOException
 */
@Test
public void copyFromLocal() throws IOException {
    fs.copyFromLocalFile(new Path("D:\\Workspaces\\Java20190715\\hdfs20190817\\src\\main\\java\\Files\\1.txt"),
            new Path("/HDFSClientTest/copyFromLocalMethod.txt"));
}
           
HDFS(上):HDFS優缺點、HDFS操作、HDFS用戶端操作、HDFS的API、HDFS資料流、HDFS的IO流、HDFS讀寫資料流程、HDFS檔案處理詳解、windows安裝hadoop
/**
 * 删除檔案
 * public abstract boolean delete(Path var1, boolean var2) throws IOException;
 * @throws IOException
 */
@Test
public void deleteFile() throws IOException {
    fs.delete(new Path("/HDFSClientTest/copyFromLocalMethod.txt"), true);
}
           
HDFS(上):HDFS優缺點、HDFS操作、HDFS用戶端操作、HDFS的API、HDFS資料流、HDFS的IO流、HDFS讀寫資料流程、HDFS檔案處理詳解、windows安裝hadoop
/**
 * 檔案重命名
 * @throws IOException
 */
@Test
public void renameFile() throws IOException {
    fs.rename(new Path("/HDFSClientTest/copyFromLocalMethod.txt"), new Path("/HDFSClientTest/renameFileMethod.txt"));
}
           
HDFS(上):HDFS優缺點、HDFS操作、HDFS用戶端操作、HDFS的API、HDFS資料流、HDFS的IO流、HDFS讀寫資料流程、HDFS檔案處理詳解、windows安裝hadoop
/**
 * 檢視檔案資訊
 * 周遊檔案名稱、權限、長度、塊資訊
 *
 * @throws IOException
 */
@Test
public void listFile() throws IOException {
    RemoteIterator<LocatedFileStatus> listFiles = fs.listFiles(new Path("/"), true);
    //周遊檔案資訊
    while (listFiles.hasNext()) {
        LocatedFileStatus next = listFiles.next();
        //路徑名及檔案名
        String name = next.getPath().getName();
        System.out.print(name + "\t");
        //檔案長度
        System.out.print(next.getLen() + "\t");
        //權限和分組
        System.out.println(next.getPermission() + " Group:" + next.getGroup());
        //擷取存儲塊資訊并周遊
        BlockLocation[] blockLocations = next.getBlockLocations();
        for (BlockLocation bk : blockLocations) {
            //擷取存儲主機節點
            String[] hosts = bk.getHosts();
            for (String host : hosts) {
                System.out.println(name + "的主機節點名:" + host);
            }
        }
    }
}
           
HDFS(上):HDFS優缺點、HDFS操作、HDFS用戶端操作、HDFS的API、HDFS資料流、HDFS的IO流、HDFS讀寫資料流程、HDFS檔案處理詳解、windows安裝hadoop
/**
 * 判斷檔案類型是檔案還是檔案夾(軟連接配接)
 *
 * @throws IOException
 */
@Test
public void fileType() throws IOException {
    FileStatus[] fileStatuses = fs.listStatus(new Path("/"));
    //周遊檔案
    for (FileStatus fst : fileStatuses) {
        //如果是檔案
        if (fst.isFile()) System.out.println(fst.getPath().getName()+"是檔案。");
        //如果是檔案夾或軟連接配接
        else System.out.println(fst.getPath().getName()+"是目錄或者連結");
    }
}
           
HDFS(上):HDFS優缺點、HDFS操作、HDFS用戶端操作、HDFS的API、HDFS資料流、HDFS的IO流、HDFS讀寫資料流程、HDFS檔案處理詳解、windows安裝hadoop
HDFS的IO流操作在下面一節
/**
 * 使用IO流上傳檔案
 * public static void copyBytes(
 * @NotNull java.io.InputStream in,
 * java.io.OutputStream out,
 * @NotNull org.apache.hadoop.conf.Configuration conf)
 */
@Test
public void putIO() throws IOException {
    //建立IO流對象
    FileInputStream fi = new FileInputStream(new File("D:\\Workspaces\\Java20190715\\hdfs20190817\\src\\main\\java\\Files\\1.txt"));
    FSDataOutputStream fo = fs.create(new Path("/HDFSClientTest/putIOTest.txt"));
    //使用IOUtils進行流對拷
    IOUtils.copyBytes(fi, fo, configuration);
    //關閉資源
    IOUtils.closeStream(fo);
    IOUtils.closeStream(fi);
}
           
HDFS(上):HDFS優缺點、HDFS操作、HDFS用戶端操作、HDFS的API、HDFS資料流、HDFS的IO流、HDFS讀寫資料流程、HDFS檔案處理詳解、windows安裝hadoop
/**
 * 分塊讀取HDFS上的大檔案,讀2第一塊
 * @throws IOException
 */
@Test
public void readFileSeek1() throws IOException {
    //建立輸入輸出流對象
    FSDataInputStream fi = fs.open(new Path("/HDFSClientTest/putIOTest.txt"));
    FileOutputStream fo = new FileOutputStream(new File("D:\\Workspaces\\Java20190715\\hdfs20190817\\src\\main\\java\\Files\\FileSeek1.txt"));
    //拷貝流
    byte[] buf = new byte[1024];
    for (int i = 0; i <1024*128; i++) {
        fi.read(buf);
        fo.write(buf);
    }
    //關閉資源
    IOUtils.closeStream(fo);
    IOUtils.closeStream(fi);
}
           

由于檔案過小出現這種情況

HDFS(上):HDFS優缺點、HDFS操作、HDFS用戶端操作、HDFS的API、HDFS資料流、HDFS的IO流、HDFS讀寫資料流程、HDFS檔案處理詳解、windows安裝hadoop
/**
 * 分塊讀取HDFS上的大檔案,讀第二塊
 *
 * @throws IOException
 */
@Test
public void readFileSeek2() throws IOException {
    //建立輸入輸出流對象
    FSDataInputStream fi = fs.open(new Path("/HDFSClientTest/putIOTest.txt"));
    FileOutputStream fo = new FileOutputStream(new File("D:\\Workspaces\\Java20190715\\hdfs20190817\\src\\main\\java\\Files\\FileSeek2.txt"));
    //拷貝流
    IOUtils.copyBytes(fi, fo, configuration);
    //關閉資源
    IOUtils.closeStream(fo);
    IOUtils.closeStream(fi);
}
}
           
HDFS(上):HDFS優缺點、HDFS操作、HDFS用戶端操作、HDFS的API、HDFS資料流、HDFS的IO流、HDFS讀寫資料流程、HDFS檔案處理詳解、windows安裝hadoop

3.3 HDFS的I/O流操作(擴充)

上面我們學的API操作HDFS系統都是架構封裝好的。那麼如果我們想自己實作上述API的操作該怎麼實作呢?

我們可以采用IO流的方式實作資料的上傳和下載下傳。

3.3.1 HDFS檔案上傳

1.需求:把本地e盤上的banhua.txt檔案上傳到HDFS根目錄

2.編寫代碼

@Test
public void putFileToHDFS() throws IOException, InterruptedException, URISyntaxException {

	// 1 擷取檔案系統
	Configuration configuration = new Configuration();
	FileSystem fs = FileSystem.get(new URI("hdfs://hadoop102:9000"), configuration, "atguigu");

	// 2 建立輸入流
	FileInputStream fis = new FileInputStream(new File("e:/banhua.txt"));

	// 3 擷取輸出流
	FSDataOutputStream fos = fs.create(new Path("/banhua.txt"));

	// 4 流對拷
	IOUtils.copyBytes(fis, fos, configuration);

	// 5 關閉資源
	IOUtils.closeStream(fos);
	IOUtils.closeStream(fis);
    fs.close();
}
           

3.3.2 HDFS檔案下載下傳

1.需求:從HDFS上下載下傳banhua.txt檔案到本地e盤上

2.編寫代碼

// 檔案下載下傳
@Test
public void getFileFromHDFS() throws IOException, InterruptedException, URISyntaxException{

	// 1 擷取檔案系統
	Configuration configuration = new Configuration();
	FileSystem fs = FileSystem.get(new URI("hdfs://hadoop102:9000"), configuration, "atguigu");
		
	// 2 擷取輸入流
	FSDataInputStream fis = fs.open(new Path("/banhua.txt"));
		
	// 3 擷取輸出流
	FileOutputStream fos = new FileOutputStream(new File("e:/banhua.txt"));
		
	// 4 流的對拷
	IOUtils.copyBytes(fis, fos, configuration);
		
	// 5 關閉資源
	IOUtils.closeStream(fos);
	IOUtils.closeStream(fis);
	fs.close();
}
           

3.3.3 定位檔案讀取

1.需求:分塊讀取HDFS上的大檔案,比如根目錄下的/hadoop-2.7.2.tar.gz

2.編寫代碼

(1)下載下傳第一塊

@Test
public void readFileSeek1() throws IOException, InterruptedException, URISyntaxException{

	// 1 擷取檔案系統
	Configuration configuration = new Configuration();
	FileSystem fs = FileSystem.get(new URI("hdfs://hadoop102:9000"), configuration, "atguigu");
		
	// 2 擷取輸入流
	FSDataInputStream fis = fs.open(new Path("/hadoop-2.7.2.tar.gz"));
		
	// 3 建立輸出流
	FileOutputStream fos = new FileOutputStream(new File("e:/hadoop-2.7.2.tar.gz.part1"));
		
	// 4 流的拷貝
	byte[] buf = new byte[1024];
		
	for(int i =0 ; i < 1024 * 128; i++){
		fis.read(buf);
		fos.write(buf);
	}
		
	// 5關閉資源
	IOUtils.closeStream(fis);
	IOUtils.closeStream(fos);
fs.close();
}
           

(2)下載下傳第二塊

@Test
public void readFileSeek2() throws IOException, InterruptedException, URISyntaxException{

	// 1 擷取檔案系統
	Configuration configuration = new Configuration();
	FileSystem fs = FileSystem.get(new URI("hdfs://hadoop102:9000"), configuration, "atguigu");
		
	// 2 打開輸入流
	FSDataInputStream fis = fs.open(new Path("/hadoop-2.7.2.tar.gz"));
		
	// 3 定位輸入資料位置
	fis.seek(1024*1024*128);
		
	// 4 建立輸出流
	FileOutputStream fos = new FileOutputStream(new File("e:/hadoop-2.7.2.tar.gz.part2"));
		
	// 5 流的對拷
	IOUtils.copyBytes(fis, fos, configuration);
		
	// 6 關閉資源
	IOUtils.closeStream(fis);
	IOUtils.closeStream(fos);
}
           

(3)合并檔案

在Window指令視窗中進入到目錄E:\,然後執行如下指令,對資料進行合并

type hadoop-2.7.2.tar.gz.part2 >> hadoop-2.7.2.tar.gz.part1

合并完成後,将hadoop-2.7.2.tar.gz.part1重新命名為hadoop-2.7.2.tar.gz。解壓發現該tar包非常完整。

第4章 HDFS的資料流(面試重點)

4.1 HDFS寫資料流程

4.1.1 剖析檔案寫入

HDFS寫資料流程,如圖3-8所示。

HDFS(上):HDFS優缺點、HDFS操作、HDFS用戶端操作、HDFS的API、HDFS資料流、HDFS的IO流、HDFS讀寫資料流程、HDFS檔案處理詳解、windows安裝hadoop

圖3-8 配置使用者名稱

1)用戶端通過Distributed FileSystem子產品向NameNode請求上傳檔案,NameNode檢查目标檔案是否已存在,父目錄是否存在。

2)NameNode傳回是否可以上傳。

3)用戶端請求第一個 Block上傳到哪幾個DataNode伺服器上。

4)NameNode傳回3個DataNode節點,分别為dn1、dn2、dn3。

5)用戶端通過FSDataOutputStream子產品請求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步)。

4.1.2 網絡拓撲-節點距離計算

在HDFS寫資料的過程中,NameNode會選擇距離待上傳資料最近距離的DataNode接收資料。那麼這個最近距離怎麼計算呢?

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

HDFS(上):HDFS優缺點、HDFS操作、HDFS用戶端操作、HDFS的API、HDFS資料流、HDFS的IO流、HDFS讀寫資料流程、HDFS檔案處理詳解、windows安裝hadoop

圖3-9 網絡拓撲概念

例如,假設有資料中心d1機架r1中的節點n1。該節點可以表示為/d1/r1/n1。利用這種标記,這裡給出四種距離描述,如圖3-9所示。

大家算一算每兩個節點之間的距離,如圖3-10所示。

HDFS(上):HDFS優缺點、HDFS操作、HDFS用戶端操作、HDFS的API、HDFS資料流、HDFS的IO流、HDFS讀寫資料流程、HDFS檔案處理詳解、windows安裝hadoop

圖3-10 網絡拓撲

4.1.3 機架感覺(副本存儲節點選擇)

1.官方ip位址

機架感覺說明

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

For the common case, when the replication factor is three, HDFS’s placement policy is to put one replica on one node in the local rack, another on a different node in the local rack, and the last on a different node in a different rack.

2.Hadoop2.7.2副本節點選擇

第一個副本在Client所處的節點上。

如果用戶端在叢集外,随機選一個。

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

第三個副本位于不同機架,随機節點。

HDFS(上):HDFS優缺點、HDFS操作、HDFS用戶端操作、HDFS的API、HDFS資料流、HDFS的IO流、HDFS讀寫資料流程、HDFS檔案處理詳解、windows安裝hadoop

4.2 HDFS讀資料流程

HDFS的讀資料流程,如圖3-13所示。

HDFS(上):HDFS優缺點、HDFS操作、HDFS用戶端操作、HDFS的API、HDFS資料流、HDFS的IO流、HDFS讀寫資料流程、HDFS檔案處理詳解、windows安裝hadoop

圖3-13 HDFS讀資料流程

1)用戶端通過Distributed FileSystem向NameNode請求下載下傳檔案,NameNode通過查詢中繼資料,找到檔案塊所在的DataNode位址。

2)挑選一台DataNode(就近原則,然後随機)伺服器,請求讀取資料。

3)DataNode開始傳輸資料給用戶端(從磁盤裡面讀取資料輸入流,以Packet為機關來做校驗)。

4)用戶端以Packet為機關接收,先在本地緩存,然後寫入目标檔案。

HDFS(下)詳細介紹NameNode、DataNode、HDFS2.x新特性及HDFS HA高可用

繼續閱讀