太原自助建站軟件快速排名教程
- 1、HDFS的API操作
- 1.1 客戶端環(huán)境準(zhǔn)備
- 1.2 API創(chuàng)建文件夾
- 1.3 API上傳
- 1.4 API參數(shù)的優(yōu)先級(jí)
- 1.5 API文件夾下載
- 1.6 API文件刪除
- 1.7 API文件更名和移動(dòng)
- 1.8 API文件詳情和查看
- 1.9 API文件和文件夾判斷
- 2、HDFS的讀寫流程(面試重點(diǎn))
- 2.1 HDFS寫數(shù)據(jù)流程
- 2.2 網(wǎng)絡(luò)拓?fù)?節(jié)點(diǎn)距離計(jì)算
- 2.3 機(jī)架感知(副本存儲(chǔ)節(jié)點(diǎn)選擇)
- 2.4 讀數(shù)據(jù)流程
1、HDFS的API操作
1.1 客戶端環(huán)境準(zhǔn)備
- 首先要配置環(huán)境變量
- 其次在IDEA中創(chuàng)建一個(gè)Maven工程HdfsClientDemo,并導(dǎo)入相應(yīng)的依賴坐標(biāo)+日志添加
<properties><maven.compiler.source>8</maven.compiler.source><maven.compiler.target>8</maven.compiler.target></properties><dependencies><dependency><groupId>org.hamcrest</groupId><artifactId>hamcrest-core</artifactId><version>1.3</version></dependency><dependency><groupId>org.apache.hadoop</groupId><artifactId>hadoop-client</artifactId><version>3.1.3</version></dependency><dependency><groupId>junit</groupId><artifactId>junit</artifactId><version>4.12</version></dependency><dependency><groupId>org.slf4j</groupId><artifactId>slf4j-log4j12</artifactId><version>1.7.30</version></dependency></dependencies>
</project>
1.2 API創(chuàng)建文件夾
package com.wenxin.hdfs;
import org.apache.hadoop.conf.Configuration;
import org.apache.hadoop.fs.FileSystem;
import org.apache.hadoop.fs.Path;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import java.io.IOException;
import java.net.URI;
import java.net.URISyntaxException;/*** @author Susie-Wen* @version 1.0* @description:客戶端代碼常用套路* 1、獲取一個(gè)客戶端對象* 2、執(zhí)行相關(guān)的操作命令* 3、關(guān)閉資源* HDFS zookeeper* @date 2023/12/11 12:27*/
public class HdfsClient {private FileSystem fs;@Beforepublic void init() throws URISyntaxException, IOException, InterruptedException {// 連接的集群地址URI uri = new URI("hdfs://hadoop102:8020");// 用戶String user = "root";// 創(chuàng)建一個(gè)配置文件Configuration configuration = new Configuration();// 1、獲取到了客戶端對象fs = FileSystem.get(uri, configuration, user);}@Afterpublic void close() throws IOException {// 3、關(guān)閉資源fs.close();}@Testpublic void testMkdir() throws IOException {// 2、創(chuàng)建一個(gè)文件夾fs.mkdirs(new Path("/xiyou/huaguoshan"));}
}
上面這段代碼把連接和關(guān)閉資源都進(jìn)行了封裝,更加方便。
@Before
注解標(biāo)識(shí)的方法 init() 是一個(gè)在測試方法執(zhí)行之前會(huì)被調(diào)用的初始化方法。@After
注解標(biāo)識(shí)的方法 close() 是一個(gè)在測試方法執(zhí)行之后會(huì)被調(diào)用的清理方法。
如下所示,確實(shí)創(chuàng)建了文件夾
1.3 API上傳
接下來進(jìn)行API上傳操作:使用客戶端遠(yuǎn)程訪問HDFS,之后上傳文件。
// 上傳:客戶端遠(yuǎn)程訪問HDFS,之后上傳文件@Testpublic void testPut() throws IOException {fs.copyFromLocalFile(false,false,new Path("E:\\VMWare\\Centos\\sunwukong.txt"),new Path("hdfs://hadoop102/xiyou/huaguoshan"));}
1.4 API參數(shù)的優(yōu)先級(jí)
HDFS文件上傳(測試參數(shù)優(yōu)先級(jí))
1)編寫源代碼
@Test
public void testCopyFromLocalFile() throws IOException, InterruptedException, URISyntaxException {// 1 獲取文件系統(tǒng)Configuration configuration = new Configuration();configuration.set("dfs.replication", "2");FileSystem fs = FileSystem.get(new URI("hdfs://hadoop102:8020"), configuration, "atguigu");// 2 上傳文件fs.copyFromLocalFile(new Path("d:/sunwukong.txt"), new Path("/xiyou/huaguoshan"));// 3 關(guān)閉資源fs.close();
}
2)將hdfs-site.xml拷貝到項(xiàng)目的resources資源目錄下
<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet type="text/xsl" href="configuration.xsl"?><configuration><property><name>dfs.replication</name><value>1</value></property>
</configuration>
參數(shù)優(yōu)先級(jí)排序:(1)客戶端代碼中設(shè)置的值 >(2)ClassPath下的用戶自定義配置文件 >(3)然后是服務(wù)器的自定義配置(xxx-site.xml) >(4)服務(wù)器的默認(rèn)配置(xxx-default.xml)
1.5 API文件夾下載
下載相當(dāng)于從HDFS將文件下載到windows本地:
//下載:將文件從HDFS下載到windows當(dāng)中public void testGet() throws IOException {fs.copyToLocalFile(false,new Path("hdfs://hadoop102/xiyou/huaguoshan"),new Path("E:\\VMWare\\"),false);}
- 如果參數(shù)四設(shè)置為true的話,就不會(huì)進(jìn)行crc校驗(yàn)
1.6 API文件刪除
//刪除@Testpublic void testRm() throws IOException {fs.delete(new Path("/xiyou/huaguoshan/sunwukong.txt"),false);}
- 除了刪除文件之外,我們還可以刪除空目錄以及非空目錄
- 多個(gè)文件如果是非遞歸刪除的話,會(huì)報(bào)錯(cuò)
//刪除@Testpublic void testRm() throws IOException {//1.刪除文件fs.delete(new Path("/xiyou/huaguoshan/sunwukong.txt"),false);//2.刪除空目錄fs.delete(new Path("/xiyou"),false);//3.刪除非空目錄fs.delete(new Path("/xiyou/huaguoshan/"),false);}
1.7 API文件更名和移動(dòng)
- 包括文件名稱的修改,文件的移動(dòng)和更名以及目錄的更名
//文件的更名和移動(dòng)@Testpublic void testMove() throws IOException {//1.文件名稱的修改fs.rename(new Path("/input/word.txt"),new Path("/input/ss.txt"));//2.文件的移動(dòng)和更名:從input目錄移動(dòng)到根目錄下并修改姓名fs.rename(new Path("/input/ss.txt"),new Path("/wenxin.txt"));//3.目錄的更名fs.rename(new Path("/input"),new Path("/output"));}
1.8 API文件詳情和查看
查看文件名稱、權(quán)限、長度、塊信息
//獲取文件詳情信息@Testpublic void fileDetail() throws IOException {//1.獲取所有文件信息RemoteIterator<LocatedFileStatus> listFiles=fs.listFiles(new Path("/"), true);//2.遍歷文件while(listFiles.hasNext()){LocatedFileStatus fileStatus=listFiles.next();System.out.println("====="+fileStatus.getPath()+"=====");System.out.println(fileStatus.getPermission());System.out.println(fileStatus.getOwner());System.out.println(fileStatus.getPath());System.out.println(fileStatus.getModificationTime());System.out.println(fileStatus.getReplication());System.out.println(fileStatus.getBlockLocations());System.out.println(fileStatus.getPath().getName());}}
//獲取文件詳情信息@Testpublic void fileDetail() throws IOException {//1.獲取所有文件信息RemoteIterator<LocatedFileStatus> listFiles=fs.listFiles(new Path("/"), true);//2.遍歷文件while(listFiles.hasNext()){LocatedFileStatus fileStatus=listFiles.next();System.out.println("====="+fileStatus.getPath()+"=====");System.out.println(fileStatus.getPermission());System.out.println(fileStatus.getOwner());System.out.println(fileStatus.getPath());System.out.println(fileStatus.getModificationTime());System.out.println(fileStatus.getReplication());System.out.println(fileStatus.getBlockLocations());System.out.println(fileStatus.getPath().getName());//獲取塊信息BlockLocation[] blockLocations = fileStatus.getBlockLocations();System.out.println(Arrays.toString(blockLocations));}}
1.9 API文件和文件夾判斷
判斷根目錄那個(gè)是文件,那個(gè)是文件夾
//判斷文件與文件夾@Testpublic void testFile() throws IOException{FileStatus[] listStatus = fs.listStatus(new Path("/"));for(FileStatus status:listStatus){if(status.isFile()){System.out.println("文件:"+status.getPath().getName());}else{System.out.println("目錄:"+status.getPath().getName());}}}
2、HDFS的讀寫流程(面試重點(diǎn))
2.1 HDFS寫數(shù)據(jù)流程
(1)客戶端通過Distributed FileSystem模塊向NameNode請求上傳文件,NameNode檢查目標(biāo)文件是否已存在,父目錄是否存在。
(2)NameNode返回是否可以上傳。
(3)客戶端請求第一個(gè) Block上傳到哪幾個(gè)DataNode服務(wù)器上。
(4)NameNode返回3個(gè)DataNode節(jié)點(diǎn),分別為dn1、dn2、dn3。
(5)客戶端通過FSDataOutputStream模塊請求dn1上傳數(shù)據(jù),dn1收到請求會(huì)繼續(xù)調(diào)用dn2,然后dn2調(diào)用dn3,將這個(gè)通信管道建立完成。
(6)dn1、dn2、dn3逐級(jí)應(yīng)答客戶端。
(7)客戶端開始往dn1上傳第一個(gè)Block(先從磁盤讀取數(shù)據(jù)放到一個(gè)本地內(nèi)存緩存),以Packet為單位,dn1收到一個(gè)Packet就會(huì)傳給dn2,dn2傳給dn3;dn1每傳一個(gè)packet會(huì)放入一個(gè)應(yīng)答隊(duì)列等待應(yīng)答。
(8)當(dāng)一個(gè)Block傳輸完成之后,客戶端再次請求NameNode上傳第二個(gè)Block的服務(wù)器。(重復(fù)執(zhí)行3-7步)。
2.2 網(wǎng)絡(luò)拓?fù)?節(jié)點(diǎn)距離計(jì)算
在HDFS寫數(shù)據(jù)的過程中,NameNode會(huì)選擇距離待上傳數(shù)據(jù)最近距離的DataNode接收數(shù)據(jù)。那么這個(gè)最近距離怎么計(jì)算呢?
節(jié)點(diǎn)距離:兩個(gè)節(jié)點(diǎn)到達(dá)最近的共同祖先的距離總和。
例如,假設(shè)有數(shù)據(jù)中心d1機(jī)架r1中的節(jié)點(diǎn)n1。該節(jié)點(diǎn)可以表示為/d1/r1/n1。利用這種標(biāo)記,這里給出四種距離描述。
算一算每兩個(gè)節(jié)點(diǎn)之間的距離:
2.3 機(jī)架感知(副本存儲(chǔ)節(jié)點(diǎn)選擇)
官方說明:
對于常見情況,當(dāng)副本為3時(shí),HDFS的放置策略是,如果編寫器在datanode上,則將一個(gè)副本放在本地計(jì)算機(jī)上,否則放在隨機(jī)datanode上,另一個(gè)副本放在不同(遠(yuǎn)程)機(jī)架中的節(jié)點(diǎn)上,最后一個(gè)放在同一遠(yuǎn)程機(jī)架中的不同節(jié)點(diǎn)上。此策略減少了機(jī)架間的寫入流量,從而總體上提高了寫入性能。機(jī)架故障的幾率遠(yuǎn)小于節(jié)點(diǎn)故障的幾率;該策略不影響數(shù)據(jù)可靠性和可用性保證。但是,它確實(shí)減少了讀取數(shù)據(jù)時(shí)使用的聚合網(wǎng)絡(luò)帶寬,因?yàn)橐粋€(gè)數(shù)據(jù)塊只放在兩個(gè)不同的機(jī)架中,而不是三個(gè)。使用此策略,文件的副本不會(huì)均勻分布在機(jī)架上。三分之一的副本位于一個(gè)節(jié)點(diǎn)上,三分之二的副本位于一個(gè)機(jī)架上,另外三分之一的副本均勻分布在其余機(jī)架上。該策略提高了寫入性能,而不影響數(shù)據(jù)可靠性或讀取性能。
- 第一個(gè)副本考慮的是節(jié)點(diǎn)距離最近,上傳速度最快。
- 第二個(gè)節(jié)點(diǎn)保證數(shù)據(jù)的可靠性。
- 第三個(gè)節(jié)點(diǎn)在保證數(shù)據(jù)可靠性的前提下兼顧效率。
查看源碼:
Crtl + n 查找BlockPlacementPolicyDefault,在該類中查找chooseTargetInOrder方法。
2.4 讀數(shù)據(jù)流程
(1)客戶端通過DistributedFileSystem向NameNode請求下載文件,NameNode通過查詢元數(shù)據(jù),找到文件塊所在的DataNode地址?!綝istributedFileSystem是分布式文件系統(tǒng)對象】
(2)挑選一臺(tái)DataNode(就近原則,然后隨機(jī))服務(wù)器,請求讀取數(shù)據(jù)?!境丝紤]節(jié)點(diǎn)最近之外,還會(huì)考慮當(dāng)前節(jié)點(diǎn)的負(fù)載能力】
(3)DataNode開始傳輸數(shù)據(jù)給客戶端(從磁盤里面讀取數(shù)據(jù)輸入流,以Packet為單位來做校驗(yàn))。
(4)客戶端以Packet為單位接收,先在本地緩存,然后寫入目標(biāo)文件。
- 這里讀取數(shù)據(jù)采用的是串行讀取,而不是并行讀取。