1 HDFS 概述
1.1 HDFS 產(chǎn)出背景及定義
隨著數(shù)據(jù)量越來越大宛畦,在一個操作系統(tǒng)存不下所有的數(shù)據(jù),那么就分配到更多的操作系統(tǒng)管理的磁盤中碍沐,但是不方便管理和維護(hù)佃扼,迫切需要一種系統(tǒng)來管理多臺機(jī)器上的文件,這就是分布式文件管理系統(tǒng)微王。HDFS只是分布式文件管理系統(tǒng)中的一種屡限。
HDFS(Hadoop Distributed File System),它是一個文件系統(tǒng)炕倘,用于存儲文件钧大,通過目錄樹來定位文件;其次罩旋,它是分布式的啊央,由很多服務(wù)器聯(lián)合起來實(shí)現(xiàn)其功能眶诈,集群中的服務(wù)器有各自的角色。
HDFS的使用場景:適合一次寫入瓜饥,多次讀出的場景逝撬,且不支持文件的修改。適合用來做數(shù)據(jù)分析乓土,并不適合用來做網(wǎng)盤應(yīng)用宪潮。
1.2 HDFS優(yōu)缺點(diǎn)
優(yōu)點(diǎn):
- 高容錯性
- 數(shù)據(jù)自動保存多個副本。它通過增加副本的形式趣苏,提高容錯性
- 某一個副本丟失以后狡相,它可以自動恢復(fù)
- 適合處理大數(shù)據(jù)
- 可構(gòu)建在廉價(jià)機(jī)器上,通過多副本機(jī)制食磕,提高可靠性
缺點(diǎn):
- 不適合低延時(shí)數(shù)據(jù)訪問尽棕,比如毫秒級的存儲數(shù)據(jù)
- 無法高效的對大量小文件進(jìn)行存儲
- 不支持并發(fā)寫入、文件隨機(jī)修改
1.3 HDFS組成架構(gòu)
1.4 HDFS文件塊大小
HDFS 中的文件在物理上是分塊存儲(Block)彬伦,塊的大小可以通過配置參數(shù)(dfs.blocksize)來規(guī)定滔悉,默認(rèn)大小在Hadoop2.x 版本中是 128M,老版本中是 64M媚朦。
如果尋址時(shí)間為 100ms氧敢,即查找目標(biāo) Block 的時(shí)間是 100ms。
尋址時(shí)間與傳輸時(shí)間的比例為 100 : 1為最佳狀態(tài)询张,因此傳輸時(shí)間為 1ms孙乖。
目前磁盤的傳輸速率大概在 100MB/s,取個整大概就是 128MB份氧。
2 HDFS 的 Shell 操作
(1)-help:輸出這個命令參數(shù)
(2)-ls:顯示目錄信息
(3)-mkdir:在 HDFS 上創(chuàng)建目錄
(4)-moveFromLocal:從本地剪切粘貼到 HDFS
(5)-appendToFile:追加一個文件到已經(jīng)存在的文件末尾
(6)-cat:顯示文件內(nèi)容
(7)-chgrp 唯袄、-chmod、-chown:Linux 文件系統(tǒng)中的用法一樣蜗帜,修改文件所屬權(quán)限
(8)-copyFromLocal:從本地文件系統(tǒng)中拷貝文件到 HDFS 路徑去
(9)-copyToLocal:從 HDFS 拷貝到本地
(10)-cp :從 HDFS 的一個路徑拷貝到 HDFS 的另一個路徑
(11)-mv:在 HDFS 目錄中移動文件
(12)-get:等同于 copyToLocal恋拷,就是從 HDFS 下載文件到本地
(13)-getmerge:合并下載多個文件,比如 HDFS 的目錄 /user/djm/test 下有多個文件:log.1, log.2,log.3,...
(14)-put:等同于 copyFromLocal
(15)-tail:顯示一個文件的末尾
(16)-rm:刪除文件或文件夾
(17)-rmdir:刪除空目錄
(18)-du:統(tǒng)計(jì)文件夾的大小信息
(19)-setrep:設(shè)置 HDFS 中文件的副本數(shù)量
3 HDFS 客戶端操作
package com.djm.hdfsclient;
import org.apache.hadoop.conf.Configuration;
import org.apache.hadoop.fs.*;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import java.io.IOException;
import java.net.URI;
public class HdfsClient {
FileSystem fileSystem = null;
@Before
public void init() {
try {
fileSystem = FileSystem.get(URI.create("hdfs://hadoop102:9000"), new Configuration(), "djm");
} catch (IOException e) {
e.printStackTrace();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
/**
* 上傳文件
*/
@Test
public void put() {
try {
fileSystem.copyFromLocalFile(new Path("C:\\Users\\Administrator\\Desktop\\Hadoop 入門.md"), new Path("/"));
} catch (IOException e) {
e.printStackTrace();
}
}
/**
* 下載文件
*/
@Test
public void download() {
try {
// useRawLocalFileSystem表示是否開啟文件校驗(yàn)
fileSystem.copyToLocalFile(false, new Path("/Hadoop 入門.md"), new Path("C:\\Users\\Administrator\\Desktop\\Hadoop 入門1.md"), true);
} catch (IOException e) {
e.printStackTrace();
}
}
/**
* 刪除文件
*/
@Test
public void delete() {
try {
// recursive表示是否遞歸刪除
fileSystem.delete(new Path("/Hadoop 入門.md"), true);
} catch (IOException e) {
e.printStackTrace();
}
}
/**
* 文件重命名
*/
@Test
public void rename() {
try {
fileSystem.rename(new Path("/tmp"), new Path("/temp"));
} catch (IOException e) {
e.printStackTrace();
}
}
/**
* 查看文件信息
*/
@Test
public void ls() {
try {
RemoteIterator<locatedfilestatus> listFiles = fileSystem.listFiles(new Path("/etc"), true);
while (listFiles.hasNext()) {
LocatedFileStatus fileStatus = listFiles.next();
if (fileStatus.isFile()) {
// 僅輸出文件信息
System.out.print(fileStatus.getPath().getName() + " " + fileStatus.getLen() + " " + fileStatus.getPermission() + " " + fileStatus.getGroup() + " ");
// 獲取文件塊信息
BlockLocation[] blockLocations = fileStatus.getBlockLocations();
for (BlockLocation blockLocation : blockLocations) {
// 獲取節(jié)點(diǎn)信息
String[] hosts = blockLocation.getHosts();
for (String host : hosts) {
System.out.print(host + " ");
}
}
System.out.println();
}
}
} catch (IOException e) {
e.printStackTrace();
}
}
@After
public void exit() {
try {
fileSystem.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
4 HDFS 的數(shù)據(jù)流
4.1 HDFS寫數(shù)據(jù)流程
4.1.1 剖析文件寫入
1厅缺、客戶端通過 Distributed FileSystem 模塊向 NameNode 請求上傳文件蔬顾,NameNode 檢查目標(biāo)文件是否已存在,父目錄是否存在湘捎。
2诀豁、NameNode 返回是否可以上傳。
3窥妇、客戶端請求第一個 Block 上傳到哪幾個 DataNode舷胜。
4、NameNode 返回三個節(jié)點(diǎn)活翩,分別是 dn1烹骨、dn2翻伺、dn3。
5沮焕、客戶端通過 FSDataOutputStream 模塊請求 dn1 上傳數(shù)據(jù)吨岭,dn1 收到請求會繼續(xù)調(diào)用 dn2,然后 dn2 調(diào)用 dn3峦树,將這個通信管道建立完成未妹。
6、按倒序逐級響應(yīng)客戶端空入。
7、客戶端開始往 dn1 上傳第一個 Block(先從磁盤讀取數(shù)據(jù)放到一個本地內(nèi)存緩存)族檬,以 Packet 為單位歪赢,dn1 收到一個Packet 就會傳給 dn2,dn2 傳給 dn3单料;dn1 每傳一個 packet 會放入一個應(yīng)答隊(duì)列等待應(yīng)答埋凯。
8、當(dāng)一個Block傳輸完成之后扫尖,客戶端再次請求NameNode上傳第二個Block的服務(wù)器白对。
4.1.2 網(wǎng)絡(luò)拓?fù)?節(jié)點(diǎn)距離計(jì)算
在HDFS寫數(shù)據(jù)的過程中,NameNode會選擇距離待上傳數(shù)據(jù)最近距離的DataNode接收數(shù)據(jù)换怖。那么這個最近距離怎么計(jì)算呢甩恼?
4.1.3 機(jī)架感知
4.2 HDFS讀數(shù)據(jù)流程
1、客戶端通過 Distributed FileSystem 向 NameNode 請求下載文件沉颂,NameNode通過查詢元數(shù)據(jù)条摸,找到文件塊所在的DataNode地址。
2铸屉、根據(jù)就近原則挑選一臺 DataNode钉蒲,請求讀取數(shù)據(jù)。
3彻坛、DataNode 開始傳輸數(shù)據(jù)給客戶端顷啼。
4、客戶端以 Packet 為單位接收昌屉,先在本地緩存钙蒙,然后寫入目標(biāo)文件。
5 NameNode 和 SecondaryNameNode
5.1 NN 和 2NN 工作機(jī)制
如果存儲在 NameNode 節(jié)點(diǎn)的磁盤中怠益,因?yàn)榻?jīng)常需要進(jìn)行隨機(jī)訪問仪搔,還有響應(yīng)客戶請求,必然是效率過低蜻牢,因此烤咧,元數(shù)據(jù)必須存放在內(nèi)存中偏陪,周所周知,內(nèi)存的特點(diǎn)是速度快煮嫌,斷電后丟失數(shù)據(jù)笛谦,一旦斷電,元數(shù)據(jù)丟失昌阿,整個集群就無法工作了饥脑,因此產(chǎn)生了用于備份元數(shù)據(jù)的 FsImage。
但是這樣又會引發(fā)一個問題懦冰,當(dāng)內(nèi)存中的元數(shù)據(jù)更新時(shí)灶轰,F(xiàn)sImage 是否要同時(shí)更新,如果要同步更新刷钢,就會導(dǎo)致效率低笋颤,如果不同步更新,就會導(dǎo)致數(shù)據(jù)一致性問題内地,一旦突然斷電伴澄,就會丟失一部分?jǐn)?shù)據(jù),因此阱缓,引入了 Edits(只進(jìn)行追加操作非凌,效率很高),每當(dāng)元數(shù)據(jù)進(jìn)行增加或者修改時(shí)荆针,先追加到 Edits敞嗡,在修改內(nèi)存,這樣的話祭犯,一旦斷電秸妥,可以通過 FsImage 和 Edits 合成元數(shù)據(jù)。
但是沃粗,如果長時(shí)間添加數(shù)據(jù)到 Edits粥惧,導(dǎo)致 Edits 過大,還是會影響效率最盅,而且一旦斷電突雪,恢復(fù)元數(shù)據(jù)的時(shí)間也會相應(yīng)增加,因此涡贱,需要定期的對 FsImage 和 Edits 進(jìn)行合并咏删,如果這個操作由 NameNode 去完成,又會效率低(因?yàn)樵诤喜⒑蟛荒芴幚韺懻埱螅┪蚀剩砸肓?SecondaryNameNode督函,專門用來做合并操作。
NameNode 工作:
1、第一次啟動 NameNode格式化后辰狡,創(chuàng)建 Fsimage 和 Edits 文件锋叨,如果不是第一次啟動,直接加載編輯日志和鏡像文件到內(nèi)存宛篇。
2娃磺、客戶端對元數(shù)據(jù)進(jìn)行增刪改操作。
3叫倍、NameNode 記錄操作日志偷卧,更新滾動日志。
4吆倦、NameNode 在內(nèi)存中對元數(shù)據(jù)進(jìn)行增刪改操作听诸。
Secondary NameNode 工作:
1、Secondary NameNode 詢問 NameNode 是否需要 CheckPoint蚕泽,直接帶回 NameNode 是否檢查結(jié)果蛇更。
2、Secondary NameNode請求執(zhí)行CheckPoint赛糟。
3、NameNode 滾動正在寫的 Edits 日志砸逊。
4璧南、將滾動前的編輯日志和鏡像文件拷貝到 Secondary NameNode。
5师逸、Secondary NameNode 加載編輯日志和鏡像文件到內(nèi)存合并司倚。
6、生成新的鏡像文件 fsimage.chkpoint篓像。
7动知、拷貝 fsimage.chkpoint 到 NameNode。
8员辩、NameNode 將 fsimage.chkpoint 重命名為 fsimage盒粮。
5.2 Fsimage 和 Edits 解析
oiv 查看Fsimage 文件
- hdfs oiv -p 文件類型 -i鏡像文件 -o 轉(zhuǎn)換后文件輸出路徑
oev 查看 Edits 文件
- hdfs oev -p 文件類型 -i編輯日志 -o 轉(zhuǎn)換后文件輸出路徑
5.3 CheckPoint 時(shí)間設(shè)置
滿足以下兩個條件都會觸發(fā)合并操作:
通常情況下,SecondaryNameNode 每隔一小時(shí)執(zhí)行一次奠滑。
-
[hdfs-default.xml]
<property> <name>dfs.namenode.checkpoint.period</name> <value>3600</value> </property>
一分鐘檢查一次操作次數(shù)丹皱,當(dāng)次數(shù)到達(dá) 100 萬次就會觸發(fā)操作。
-
[hdfs-default.xml]
<property> <name>dfs.namenode.checkpoint.txns</name> <value>1000000</value> <description>操作動作次數(shù)</description> </property> <property> <name>dfs.namenode.checkpoint.check.period</name> <value>60</value> <description> 1分鐘檢查一次操作次數(shù)</description> </property>
5.4 NameNode 故障處理
NameNode 故障后宋税,可以采用如下兩種方法恢復(fù)數(shù)據(jù):
將 2NN 中的數(shù)據(jù)拷貝到 NN 存儲數(shù)據(jù)的目錄摊崭。
使用 -importCheckpoint 選項(xiàng)啟動 NN 守護(hù)進(jìn)程,從而將 2NN 中數(shù)據(jù)拷貝到 NN 目錄中杰赛。
- hdfs namenode -importCheckpoint
5.5 集群安全模式
基本命令:
hdfs dfsadmin -safemode get:查看安全模式狀態(tài)
hdfs dfsadmin -safemode enter:進(jìn)入安全模式狀態(tài)
hdfs dfsadmin -safemode leave:離開安全模式狀態(tài)
hdfs dfsadmin -safemode wait:等待安全模式狀態(tài)
6 DataNode
6.1 DataNode工作機(jī)制
1呢簸、一個數(shù)據(jù)塊在 DataNode 上以文件形式存儲在磁盤上,包括兩個文件,一個是數(shù)據(jù)本身根时,一個是元數(shù)據(jù)包括數(shù)據(jù)塊的長度瘦赫,塊數(shù)據(jù)的校驗(yàn)和,以及時(shí)間戳啸箫。
2耸彪、DataNode 啟動后向 NameNode 注冊,通過后忘苛,周期性(1小時(shí))的向 NameNode 上報(bào)所有的塊信息蝉娜。
3、心跳是每 3 秒一次扎唾,心跳返回結(jié)果帶有 NameNode 給該 DataNode 的命令如復(fù)制塊數(shù)據(jù)到另一臺機(jī)器召川,或刪除某個數(shù)據(jù)塊,如果超過 10 分鐘沒有收到某個 DataNode 的心跳胸遇,則認(rèn)為該節(jié)點(diǎn)不可用荧呐。
4、集群運(yùn)行中可以安全加入和退出一些機(jī)器纸镊。
6.2 數(shù)據(jù)完整性
1倍阐、當(dāng) DataNode 讀取 Block 的時(shí)候,它會計(jì)算 CheckSum逗威。
2峰搪、如果計(jì)算后的 CheckSum,與 Block 創(chuàng)建時(shí)值不一樣凯旭,說明 Block 已經(jīng)損壞概耻。
3、Client 讀取其他 DataNode 上的 Block罐呼。
4鞠柄、在其文件創(chuàng)建后周期驗(yàn)證。
6.3 掉線時(shí)限參數(shù)設(shè)置
[hdfs-site.xml]
<property>
<name>dfs.namenode.heartbeat.recheck-interval</name>
<value>300000</value>
<description>毫秒</description>
</property>
<property>
<name>dfs.heartbeat.interval</name>
<value>3</value>
<description>秒</description>
</property>
6.4 服役新數(shù)據(jù)節(jié)點(diǎn)
將 hadoop102 上的 java嫉柴、hadoop厌杜、profile 發(fā)送到新主機(jī),source 一下 profile计螺,直接啟動即可加入集群期奔。
6.5 退役舊數(shù)據(jù)節(jié)點(diǎn)
6.5.1 黑名單設(shè)置
創(chuàng)建黑名單
[djm@hadoop101 hadoop]$ touch blacklist
配置加入黑名單的主機(jī)
hadoop102
配置 hdfs-site.xml
<property>
<name>dfs.hosts.exclude</name>
<value>/opt/module/hadoop-2.7.2/etc/hadoop/blacklist</value>
</property>
刷新 namenodes
[djm@hadoop102 hadoop-2.7.2]$ hdfs dfsadmin -refreshNodes
更新 ResourceManager 節(jié)點(diǎn)
[djm@hadoop102 hadoop-2.7.2]$ yarn rmadmin -refreshNodes
如果數(shù)據(jù)不均衡,可以用命令實(shí)現(xiàn)集群的再平衡
[djm@hadoop102 hadoop-2.7.2]$ start-balancer.sh
6.5.2 白名單設(shè)置
創(chuàng)建白名單
[djm@hadoop101 hadoop]$ touch whitelist
配置加入黑名單的主機(jī)
hadoop102
hadoop103
hadoop104
配置 hdfs-site.xml
<property>
<name>dfs.hosts</name>
<value>/opt/module/hadoop-2.7.2/etc/hadoop/whitelist</value>
</property>
刷新 namenodes
[djm@hadoop102 hadoop-2.7.2]$ hdfs dfsadmin -refreshNodes
更新 ResourceManager 節(jié)點(diǎn)
[djm@hadoop102 hadoop-2.7.2]$ yarn rmadmin -refreshNodes
如果數(shù)據(jù)不均衡危尿,可以用命令實(shí)現(xiàn)集群的再平衡
[djm@hadoop102 hadoop-2.7.2]$ start-balancer.sh
黑白名單的區(qū)別:
白名單比較嚴(yán)格呐萌,黑名單比較平緩,處于黑名單中的主機(jī)會同步數(shù)據(jù)結(jié)束后繼續(xù)處于集群谊娇,只是不在處理請求而已肺孤,而不處于白名單中的主機(jī)會直接被干掉罗晕。
6.6 Datanode多目錄配置
DataNode也可以配置成多個目錄,每個目錄存儲的數(shù)據(jù)不一樣赠堵,即:數(shù)據(jù)不是副本小渊。
hdfs-site.xml
<property>
<name>dfs.datanode.data.dir</name>
<value>file:///${hadoop.tmp.dir}/dfs/data1,file:///${hadoop.tmp.dir}/dfs/data2</value>
</property>
7 HDFS 2.X新特性
7.1 集群間數(shù)據(jù)拷貝
采用 distcp 命令實(shí)現(xiàn)兩個 Hadoop 集群之間的遞歸數(shù)據(jù)復(fù)制
[djm@hadoop102 hadoop-2.7.2]$ hadoop distcp hdfs://haoop102:9000/user/djm/hello.txt hdfs://hadoop103:9000/user/djm/hello.txt
7.2 小文件存檔
歸檔文件
[djm@hadoop102 hadoop-2.7.2]$ hadoop archive -archiveName input.har –p /user/djm/input /user/djm/output
查看歸檔
[djm@hadoop102 hadoop-2.7.2]$ hadoop fs -lsr har:///user/djm/output/input.har
解歸檔文件
[atguigu@djm hadoop-2.7.2]$ hadoop fs -cp har:/// user/djm/output/input.har/* /user/djm
</locatedfilestatus>