我們在上一篇《向Hadoop Say Hello——初識Hadoop》中已經(jīng)對HDFS進(jìn)行了簡單介紹砰逻,還不清楚HDFS是什么的朋友可以點(diǎn)擊上面鏈接先看上一篇,在這一篇中我們聚焦HDFS肥缔,從HDFS的設(shè)計(jì)架構(gòu)和重要概念開始學(xué)習(xí),然后會學(xué)習(xí)HDFS的命令行操作以及Java Api操作芙代。
<font color=#dd2c00>特別提示:本文所進(jìn)行的演示都是在hadoop-2.6.0-cdh5.15.1的版本進(jìn)行的</font>
一鼓黔、HDFS概述
HDFS 是 Hadoop Distribute File System,Hadoop分布式文件系統(tǒng)的簡稱谎脯。這個(gè)文件系統(tǒng)是一個(gè)適用于大的數(shù)據(jù)集的支持高吞吐和高容錯(cuò)的運(yùn)行在通用(廉價(jià))機(jī)上的分布式文件系統(tǒng)葱跋。
設(shè)計(jì)目標(biāo)
- 故障的快速檢測和自動恢復(fù)(容錯(cuò))
分布式的文件系統(tǒng)將由成百上千臺的機(jī)器共同組成集群,在集群中每一臺機(jī)器都可能出現(xiàn)故障,當(dāng)出現(xiàn)部分機(jī)器出現(xiàn)故障時(shí)娱俺,保證服務(wù)的正常提供是一個(gè)重要的工作稍味,因此故障的快遞檢測和自動快速恢復(fù)是 HDFS 的核心設(shè)計(jì)目標(biāo)
- 流式數(shù)據(jù)訪問(高吞吐)
HDFS 的設(shè)計(jì)是為了存儲大文件,它更注重?cái)?shù)據(jù)訪問的吞吐量荠卷,對訪問的延時(shí)性要求較低模庐,它不適用于低延時(shí)的場景,為了保證大吞吐量的數(shù)據(jù)訪問油宜,HDFS 被設(shè)計(jì)成了更適合批量處理掂碱,且以流式讀取數(shù)據(jù)的方式
- 存儲大的數(shù)據(jù)集
通常情況下在HDFS上運(yùn)行的應(yīng)用都具有大的數(shù)據(jù)集,一個(gè)典型的 HDFS 文件大小是 GB 到 TB 的級別慎冤,在實(shí)際中超大型集群的HDFS中文件的大小也可能達(dá)到PB級別
- 簡化數(shù)據(jù)一致性模型
大部分運(yùn)行在 HDFS 上的應(yīng)用對文件都是"一次寫入疼燥,多次讀出"訪問模型。所以HDFS就作出了一個(gè)文件一旦創(chuàng)建粪薛、寫入成功后就不需要再修改了的假設(shè)悴了,這一假設(shè)簡化了數(shù)據(jù)一致性問題,使高吞吐量的數(shù)據(jù)訪問成為可能(后文會分析HDFS的數(shù)據(jù)一致性問題)
- 移動計(jì)算的位置比移動數(shù)據(jù)的位置更劃算
由于網(wǎng)絡(luò)帶寬是一個(gè)有限資源违寿,一個(gè)計(jì)算任務(wù)的運(yùn)行湃交,當(dāng)計(jì)算數(shù)據(jù)離計(jì)算邏輯所在節(jié)點(diǎn)越近這個(gè)計(jì)算任務(wù)執(zhí)行的就越高效,數(shù)據(jù)量越大這種特點(diǎn)就越明顯藤巢。所以在 HDFS 中設(shè)計(jì)了提供給應(yīng)用將計(jì)算邏輯移動到數(shù)據(jù)附近這樣的接口
- 可移植性
為了方便HDFS作為大規(guī)模數(shù)據(jù)應(yīng)用平臺得到廣泛應(yīng)用搞莺,HDFS被設(shè)計(jì)成了一個(gè)易于從一個(gè)平臺移植到另一個(gè)平臺的數(shù)據(jù)應(yīng)用系統(tǒng)
二、HDFS中一些概念
Block(塊)
HDFS和一般的磁盤文件系統(tǒng)一樣掂咒,也有Block的概念才沧,和一般文件相同的是,用戶存儲的文件都會被按照Block Size被拆分存儲绍刮,但與一般磁盤文件系統(tǒng)不同的是温圆,當(dāng)一個(gè)文件的實(shí)際大小比Block Size小的時(shí)候,它不會占用Block Size大小的物理空間孩革。這句話如何理解呢岁歉?
咱們舉個(gè)栗子,HDFS的默認(rèn)塊大小是128M,假設(shè)現(xiàn)在有一個(gè)200M的文件那么存儲在HDFS上時(shí)就會被拆分成兩個(gè)Block存儲膝蜈,分別是一個(gè)128M的塊和一個(gè)72M的塊锅移,且他們占用的物理空間也是200M。而在一般的磁盤文件系統(tǒng)中塊的大小是4K饱搏,不同點(diǎn)就是如果一個(gè)文件大小是5K那么它存儲在磁盤文件系統(tǒng)中所占用的物理空間大小是8k非剃,在一般磁盤文件系統(tǒng)中文件大小沒有超過一個(gè)塊大小時(shí),是按照一個(gè)塊的大小占用空間推沸。
文件系統(tǒng)命名空間
HDFS和傳統(tǒng)的文件系統(tǒng)一樣支持分層的文件組織結(jié)構(gòu)备绽。支持常用的文件創(chuàng)建券坞,刪除、移動疯坤,重命名等操作报慕,并且也支持用戶配額和訪問權(quán)限控制。現(xiàn)有的HDFS實(shí)現(xiàn)不支持硬鏈接或軟鏈接压怠。
副本機(jī)制
為了容錯(cuò)眠冈,每個(gè)文件被拆分后的 Block 都是以副本的方式存儲,每個(gè)文件的塊大小和以及復(fù)制的副本系數(shù)都是可以配置菌瘫,HDFS 默認(rèn)是3副本配置蜗顽。
在集群中副本的放置位置對HDFS的可靠性和性能都有很大的影響,所以優(yōu)化副本擺放策略在一個(gè)大型集群中顯得尤為重要雨让。在HDFS中是使用一種機(jī)架感知的副本放置策略雇盖,這種策略是基于提高數(shù)據(jù)可靠性、可用性和網(wǎng)絡(luò)帶寬利用率而設(shè)計(jì)的一種策略
在機(jī)架感知副本策略下栖忠,當(dāng)副本系數(shù)是3時(shí)崔挖,HDFS的文件副本放置方式如下:如果寫入程序位于數(shù)據(jù)節(jié)點(diǎn)上,則將一個(gè)副本放在本地計(jì)算機(jī)上庵寞,否則放在與寫入程序位于同一機(jī)架中的隨機(jī)數(shù)據(jù)節(jié)點(diǎn)上狸相,另一個(gè)副本放在不同(遠(yuǎn)程)機(jī)架中的節(jié)點(diǎn)上,最后一個(gè)放在同一遠(yuǎn)程機(jī)架中的不同節(jié)點(diǎn)上捐川。
二脓鹃、HDFS的架構(gòu)
HDFS 是一個(gè)主從架構(gòu)的服務(wù)。一個(gè) HDFS 集群包括一個(gè) NameNode 節(jié)點(diǎn)古沥、一個(gè) SecondaryNameNode 節(jié)點(diǎn)(非必須)和多個(gè) DataNode 節(jié)點(diǎn)瘸右。
NameNode
NameNode是一個(gè)主節(jié)點(diǎn),是所有 HDFS 元數(shù)據(jù)的決策器和存儲庫岩齿,它管理文件系統(tǒng)名稱空間太颤、確定塊到數(shù)據(jù)節(jié)點(diǎn)的映射,并且控制客戶端對文件的訪問盹沈。但是 NameNode 從不與用戶數(shù)據(jù)直接交互栋齿,與用戶數(shù)據(jù)交互的工作都由DataNode 來做。
DataNode
DataNode是管理它們運(yùn)行的節(jié)點(diǎn)的數(shù)據(jù)存儲襟诸,通常一個(gè)集群中每個(gè)節(jié)點(diǎn)一個(gè)都有一個(gè) DataNode。DataNode 負(fù)責(zé)為來自客戶端的讀寫請求提供服務(wù)基协,同時(shí)它還會根據(jù) NameNode 的指令執(zhí)行塊創(chuàng)建歌亲、刪除和復(fù)制。
SecondaryNameNode
SecondaryNameNode是NameNode的一個(gè)冷備份澜驮,可以看做是一個(gè)CheckPoint陷揪,它主要負(fù)責(zé)合并 fsimage 和 fsedits,并推送給 NameNode。它也會維護(hù)一個(gè)合并后的 Namespace Image 副本悍缠, 可用于在 NameNode 故障后恢復(fù)數(shù)據(jù)
架構(gòu)圖
接下來咱們可以看下面這張圖(圖片來自Hadoop官網(wǎng))卦绣,這就是HDFS的一個(gè)架構(gòu)圖
圖中的幾個(gè)要點(diǎn):
NameNode管理著Metadata(元數(shù)據(jù))
客戶端client對元數(shù)據(jù)的操作是指向NameNode,對用戶數(shù)據(jù)的讀寫是通過DataNode
NameNode向DataNode發(fā)送Block的操作命令
一塊的副本被存儲在不同的機(jī)架中
HDFS Federation
通過了解架構(gòu)大家是否發(fā)現(xiàn)了一個(gè)問題飞蚓?在 HDFS 的主從架構(gòu)中 NameNode 成了集群擴(kuò)大的瓶頸滤港,隨著集群增大和文件數(shù)據(jù)量增多,單個(gè) NameNode 性能就無法滿足需求趴拧,這也就意味著溅漾,HDFS 集群的大小是受 NameNode 節(jié)點(diǎn)約束的。
HDFS Federation( HDFS 聯(lián)邦)就是為了解決這種問題著榴,它提供了一種橫向擴(kuò)展 NameNode 的方式添履。在 Federation 模式中,每個(gè) NameNode 管理命名空間的一部分脑又,同時(shí)也各自維護(hù)一個(gè) Block Pool暮胧,保存 Block 的節(jié)點(diǎn)映射信息。各 NameNode 節(jié)點(diǎn)之間是獨(dú)立的问麸,一個(gè)節(jié)點(diǎn)的失敗不會導(dǎo)致其他節(jié)點(diǎn)管理的文件不可用往衷,同時(shí)失敗的節(jié)點(diǎn)所管理的文件數(shù)據(jù)也就不可訪問,所以 HDFS Federation 只是解決 HDFS 的拓展問題口叙,并不是解決單點(diǎn)故障問題的炼绘。
四、HDFS的安裝和使用
在剛開始學(xué)習(xí)的過程中建議先使用單機(jī)版妄田,避免因?yàn)榧旱膯栴}提高了學(xué)習(xí)門檻俺亮,打擊自己學(xué)習(xí)信心,在熟練其使用和原理后在使用集群也不遲疟呐。
HDFS的安裝可以參照《教你安裝單機(jī)版Hadoop》,這篇文章里面有講述HFDS的安裝脚曾。
HDFS安裝成功后如下操作
第一次啟動前需要對文件系統(tǒng)進(jìn)行格式化:
${HADOOP_HOME}/bin/hdfs name -format
啟動HDFS:
${HADOOP_HOME}/sbin/start-dfs.sh
在HDFS啟動后,我們就可以訪問 HDFS 的 Web 頁面启具,查看HDFS的信息本讥,HDFS web 訪問默認(rèn)端口是50070,瀏覽器打開效果如下:
首頁是一個(gè)Overview概覽信息鲁冯,里面包括了集群基本信息(Hadoop版本拷沸、集群ID、Block Pool ID等)薯演、存儲摘要以及NameNode的運(yùn)行狀態(tài)等撞芍。
在頂部第二個(gè)主菜單下是DataNode的信息,頁面效果如下:
在主菜單的最后一項(xiàng)Utilities下面有一個(gè)Browse the file system跨扮,這個(gè)頁面就是HDFS的一個(gè)文件瀏覽器序无,可以查看在HDFS上存儲的文件验毡,效果如下:
四、HDFS基本操作(命令和Java Api)
HDFS 包含的常用操作如下
命令操作
HDFS的命令有兩種使用方式
通過hadoop命令:
hadoop fs [options]
帝嗡,eg:./hadoop fs -ls /通過hdfs命令:
hdfs dfs [options]
,eg:./hdfs dfs -ls /
其實(shí)兩種方法調(diào)用的是相同的腳本代碼晶通。
常用命令中有一部分是類似于Linux的文件管理命令,對于這一部分命令可以類比Linux中的使用哟玷,我們就不講解了狮辽,我們只把HDFS中一些特別的命令學(xué)習(xí)一下。
類似Linux系統(tǒng)的文件管理命令有:<font color=#00bfa5>ls, cat, chgrp, chmod, chown, cp, df, du, find, mkdir, mv, rm, rmdir, tail, test</font>
我們學(xué)習(xí)一下這些命令:
appendToFile:將一個(gè)或者多個(gè)文件添加到HDFS系統(tǒng)中
copyFromLocal:將本地文件拷貝到HDFS
count:統(tǒng)計(jì)hdfs對應(yīng)路徑下的目錄個(gè)數(shù)碗降,文件個(gè)數(shù)隘竭,文件總計(jì)大小
expunge:從垃圾箱目錄永久刪除超過保留閾值的檢查點(diǎn)中的文件,并創(chuàng)建新檢查點(diǎn)
get:從HDFS上傳輸文件到本地
getmerge:把hdfs指定目錄下的所有文件內(nèi)容合并到本地linux的文件中
moveFromLocal:把本地文件移動到HDFS上讼渊,本地文件會被刪除
moveToLocal:把HDFS文件移動到本地动看,HDFS文件會被刪除
put:將文件上傳到HDFS上
setrep:修改文件或目錄副本數(shù)
stat:輸出指定目錄的信息,可設(shè)置格式化輸出(%b: 文件大小爪幻,%n: 文件名菱皆,%o: 塊大小,%r: 副本個(gè)數(shù)挨稿,%y, %Y: 修改日期)
text:格式化輸出文件的內(nèi)容仇轻,允許的格式化包括zip,和 TextRecordInputStream
touchz:在指定目錄創(chuàng)建一個(gè)新文件,如果文件存在奶甘,則創(chuàng)建失敗
Hadoop的文件系統(tǒng)
在使用Java的Api前我們現(xiàn)先了解一下Hadoop的抽象文件系統(tǒng)
org.apache.hadoop.fs.FileSystem 是Hadoop中抽象的一個(gè)文件系統(tǒng)篷店,我們今天所使用的HDFS只是這個(gè)抽象的文件系統(tǒng)的實(shí)現(xiàn)之一,HDFS提供了幾個(gè)主要的實(shí)現(xiàn)包括:LocalFileSystem臭家、 DistributeFileSystem疲陕、 WebHdfsFileSystem、 HarFileSystem钉赁、 ViewFileSystem蹄殃、 FtpFileSystem、 S3AFileSystem
LocalFileSystem:對本地文件系統(tǒng)的一個(gè)實(shí)現(xiàn)
DistributeFileSystem:HDFS的實(shí)現(xiàn)
WebHdfsFileSystem:通過Http請求提供對HDFS的認(rèn)證和讀寫操作的實(shí)現(xiàn),還有一個(gè)SWebHdfsFileSystem是基于Https的實(shí)現(xiàn)
HarFileSystem:這是Hadoop存檔文件系統(tǒng)的實(shí)現(xiàn)你踩,歸檔后的多個(gè)文件可以進(jìn)行壓縮成一個(gè)文件
ViewFileSystem:視圖文件系統(tǒng)诅岩,只是邏輯上唯一的一個(gè)視圖文件系統(tǒng),主要是來做HDFS Federation的時(shí)候带膜,將不同集群中的文件系統(tǒng)進(jìn)行映射吩谦,在邏輯上形成一個(gè)文件系統(tǒng),在客戶端屏蔽底層細(xì)節(jié)
FtpFileSystem:基于ftp協(xié)議的一個(gè)文件系統(tǒng)實(shí)現(xiàn)
S3AFileSystem: 基于S3A協(xié)議的一個(gè)文件系統(tǒng)實(shí)現(xiàn)膝藕,S3是Amazon的對象存儲服務(wù)
Java Api
- pom中加入hadoop-client依賴
<repositories>
<!--使用的Hadoop是CDH版本的需要引用一下cloudera的倉庫庫-->
<repository>
<id>cloudera</id>
<url>https://repository.cloudera.com/artifactory/cloudera-repos/</url>
</repository>
</repositories>
<dependencies>
<!--Hadoop客戶端-->
<dependency>
<groupId>org.apache.hadoop</groupId>
<artifactId>hadoop-client</artifactId>
<version>2.6.0-cdh5.15.1</version>
</dependency>
</dependencies>
- 一個(gè)簡單的演示代碼
package site.teamo.learning.hdfs;
import org.apache.hadoop.conf.Configuration;
import org.apache.hadoop.fs.FSDataInputStream;
import org.apache.hadoop.fs.FSDataOutputStream;
import org.apache.hadoop.fs.FileSystem;
import org.apache.hadoop.fs.Path;
import java.io.Closeable;
import java.io.IOException;
public class HdfsApp {
/**
* @param args
* @throws IOException
*/
public static void main(String[] args) throws IOException {
FileSystem fs = null;
try {
//創(chuàng)建配置逮京,設(shè)置Hdfs的地址信息
Configuration configuration = new Configuration();
configuration.set("fs.defaultFS", "hdfs://hdh100:8020");
//在系統(tǒng)環(huán)境變量設(shè)置使用的用戶名
System.setProperty("HADOOP_USER_NAME", "root");
//打開一個(gè)文件系統(tǒng)
fs = FileSystem.get(configuration);
//創(chuàng)建一個(gè)目錄
fs.mkdirs(new Path("/dream-hammer"));
//判斷是否是目錄
fs.isDirectory(new Path("/dream-hammer"));
//創(chuàng)建一個(gè)文件dream1.txt,返回值boolean類型束莫,true:創(chuàng)建成功懒棉;false:創(chuàng)建失敗
fs.createNewFile(new Path("/dream-hammer/dream1.txt"));
//判斷文件是否存在,返回值是boolean類型览绿,true:存在策严;false:不存在
fs.exists(new Path("/dream-hammer/dream1.txt"));
//向文件追加內(nèi)容
FSDataOutputStream out = null;
try {
out = fs.append(new Path("/dream-hammer/dream1.txt"));
out.writeUTF("dream-hammer");
out.flush();
out.close();
} finally {
close(out);
}
//打開dream1的輸入流
FSDataInputStream in = null;
try {
in = fs.open(new Path("/dream-hammer/dream1.txt"));
System.out.println(in.readUTF());
in.close();
} finally {
close(in);
}
//刪除目錄和文件
fs.delete(new Path("/dream-hammer"), true);
} finally {
close(fs);
}
}
/**
* 關(guān)閉流,釋放資源
* @param closeable
*/
public static void close(Closeable closeable) {
if (closeable != null) {
try {
closeable.close();
} catch (Exception e) {
e.printStackTrace();
}
}
}
}
** 總結(jié) ** :這篇文章主要是對HDFS的基礎(chǔ)理論知識進(jìn)行了介紹和說明饿敲,同時(shí)也介紹了HDFS的基本使用妻导,比較基礎(chǔ)易懂,也適合剛接觸HDFS的朋友閱讀學(xué)習(xí)怀各,錘子會在下一篇文章里面介紹 HDFS讀寫數(shù)據(jù)流程倔韭,這個(gè)屬于更深層次的東西了,關(guān)注【愛做夢的錘子】瓢对,一起學(xué)習(xí)進(jìn)步
文章歡迎轉(zhuǎn)載寿酌,轉(zhuǎn)載請注明出處,個(gè)人公眾號【愛做夢的錘子】硕蛹,全網(wǎng)同id醇疼,個(gè)站 http://te-amo.site,歡迎關(guān)注法焰,里面會分享更多有用知識秧荆,還有我的私密照片