隨著數據量越來越大,在一個操作系統存不下所有的數據,那么就分配到更多的操作系統管理的磁盤中,但是不方便管理和維護,迫切需要一種系統來管理多臺機器上的文件,這就是分布式文件管理系統。HDFS只是分布式文件管理系統中的一種。
HDFS(Hadoop Distributed File System),它是一個文件系統,用于存儲文件,通過目錄樹來定位文件;其次,它是分布式的,由很多服務器聯合起來實現其功能,集群中的服務器有各自的角色。
HDFS的使用場景:適合一次寫入,多次讀出的場景,且不支持文件的修改。適合用來做數據分析,并不適合用來做網盤應用。
優點:
缺點:
HDFS 中的文件在物理上是分塊存儲(Block),塊的大小可以通過配置參數(dfs.blocksize)來規定,默認大小在Hadoop2.x 版本中是 128M,老版本中是 64M。
如果尋址時間為 100ms,即查找目標 Block 的時間是 100ms。
尋址時間與傳輸時間的比例為 100 : 1為最佳狀態,因此傳輸時間為 1ms。
目前磁盤的傳輸速率大概在 100MB/s,取個整大概就是 128MB。
(1)-help:輸出這個命令參數
(2)-ls:顯示目錄信息
(3)-mkdir:在 HDFS 上創建目錄
(4)-moveFromLocal:從本地剪切粘貼到 HDFS
(5)-appendToFile:追加一個文件到已經存在的文件末尾
(6)-cat:顯示文件內容
(7)-chgrp 、-chmod、-chown:Linux 文件系統中的用法一樣,修改文件所屬權限
(8)-copyFromLocal:從本地文件系統中拷貝文件到 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:統計文件夾的大小信息
(19)-setrep:設置 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表示是否開啟文件校驗
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) {
// 獲取節點信息
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();
}
}
}
1、客戶端通過 Distributed FileSystem 模塊向 NameNode 請求上傳文件,NameNode 檢查目標文件是否已存在,父目錄是否存在。
2、NameNode 返回是否可以上傳。
3、客戶端請求第一個 Block 上傳到哪幾個 DataNode。
4、NameNode 返回三個節點,分別是 dn1、dn2、dn3。
5、客戶端通過 FSDataOutputStream 模塊請求 dn1 上傳數據,dn1 收到請求會繼續調用 dn2,然后 dn2 調用 dn3,將這個通信管道建立完成。
6、按倒序逐級響應客戶端。
7、客戶端開始往 dn1 上傳第一個 Block(先從磁盤讀取數據放到一個本地內存緩存),以 Packet 為單位,dn1 收到一個Packet 就會傳給 dn2,dn2 傳給 dn3;dn1 每傳一個 packet 會放入一個應答隊列等待應答。
8、當一個Block傳輸完成之后,客戶端再次請求NameNode上傳第二個Block的服務器。
在HDFS寫數據的過程中,NameNode會選擇距離待上傳數據最近距離的DataNode接收數據。那么這個最近距離怎么計算呢?
1、客戶端通過 Distributed FileSystem 向 NameNode 請求下載文件,NameNode通過查詢元數據,找到文件塊所在的DataNode地址。
2、根據就近原則挑選一臺 DataNode,請求讀取數據。
3、DataNode 開始傳輸數據給客戶端。
4、客戶端以 Packet 為單位接收,先在本地緩存,然后寫入目標文件。
如果存儲在 NameNode 節點的磁盤中,因為經常需要進行隨機訪問,還有響應客戶請求,必然是效率過低,因此,元數據必須存放在內存中,周所周知,內存的特點是速度快,斷電后丟失數據,一旦斷電,元數據丟失,整個集群就無法工作了,因此產生了用于備份元數據的 FsImage。
但是這樣又會引發一個問題,當內存中的元數據更新時,FsImage 是否要同時更新,如果要同步更新,就會導致效率低,如果不同步更新,就會導致數據一致性問題,一旦突然斷電,就會丟失一部分數據,因此,引入了 Edits(只進行追加操作,效率很高),每當元數據進行增加或者修改時,先追加到 Edits,在修改內存,這樣的話,一旦斷電,可以通過 FsImage 和 Edits 合成元數據。
但是,如果長時間添加數據到 Edits,導致 Edits 過大,還是會影響效率,而且一旦斷電,恢復元數據的時間也會相應增加,因此,需要定期的對 FsImage 和 Edits 進行合并,如果這個操作由 NameNode 去完成,又會效率低(因為在合并后不能處理寫請求),所以引入了 SecondaryNameNode,專門用來做合并操作。
NameNode 工作:
1、第一次啟動 NameNode格式化后,創建 Fsimage 和 Edits 文件,如果不是第一次啟動,直接加載編輯日志和鏡像文件到內存。
2、客戶端對元數據進行增刪改操作。
3、NameNode 記錄操作日志,更新滾動日志。
4、NameNode 在內存中對元數據進行增刪改操作。
Secondary NameNode 工作:
1、Secondary NameNode 詢問 NameNode 是否需要 CheckPoint,直接帶回 NameNode 是否檢查結果。
2、Secondary NameNode請求執行CheckPoint。
3、NameNode 滾動正在寫的 Edits 日志。
4、將滾動前的編輯日志和鏡像文件拷貝到 Secondary NameNode。
5、Secondary NameNode 加載編輯日志和鏡像文件到內存合并。
6、生成新的鏡像文件 fsimage.chkpoint。
7、拷貝 fsimage.chkpoint 到 NameNode。
8、NameNode 將 fsimage.chkpoint 重命名為 fsimage。
oiv 查看Fsimage 文件
oev 查看 Edits 文件
滿足以下兩個條件都會觸發合并操作:
通常情況下,SecondaryNameNode 每隔一小時執行一次。
[hdfs-default.xml]
<property>
<name>dfs.namenode.checkpoint.period</name>
<value>3600</value>
</property>
一分鐘檢查一次操作次數,當次數到達 100 萬次就會觸發操作。
[hdfs-default.xml]
<property>
<name>dfs.namenode.checkpoint.txns</name>
<value>1000000</value>
<description>操作動作次數</description>
</property>
<property>
<name>dfs.namenode.checkpoint.check.period</name>
<value>60</value>
<description> 1分鐘檢查一次操作次數</description>
</property>
NameNode 故障后,可以采用如下兩種方法恢復數據:
將 2NN 中的數據拷貝到 NN 存儲數據的目錄。
使用 -importCheckpoint 選項啟動 NN 守護進程,從而將 2NN 中數據拷貝到 NN 目錄中。
基本命令:
hdfs dfsadmin -safemode get:查看安全模式狀態
hdfs dfsadmin -safemode enter:進入安全模式狀態
hdfs dfsadmin -safemode leave:離開安全模式狀態
hdfs dfsadmin -safemode wait:等待安全模式狀態
1、一個數據塊在 DataNode 上以文件形式存儲在磁盤上,包括兩個文件,一個是數據本身,一個是元數據包括數據塊的長度,塊數據的校驗和,以及時間戳。
2、DataNode 啟動后向 NameNode 注冊,通過后,周期性(1小時)的向 NameNode 上報所有的塊信息。
3、心跳是每 3 秒一次,心跳返回結果帶有 NameNode 給該 DataNode 的命令如復制塊數據到另一臺機器,或刪除某個數據塊,如果超過 10 分鐘沒有收到某個 DataNode 的心跳,則認為該節點不可用。
4、集群運行中可以安全加入和退出一些機器。
1、當 DataNode 讀取 Block 的時候,它會計算 CheckSum。
2、如果計算后的 CheckSum,與 Block 創建時值不一樣,說明 Block 已經損壞。
3、Client 讀取其他 DataNode 上的 Block。
4、在其文件創建后周期驗證。
[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>
將 hadoop102 上的 java、hadoop、profile 發送到新主機,source 一下 profile,直接啟動即可加入集群。
創建黑名單
[djm@hadoop101 hadoop]$ touch blacklist
配置加入黑名單的主機
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 節點
[djm@hadoop102 hadoop-2.7.2]$ yarn rmadmin -refreshNodes
如果數據不均衡,可以用命令實現集群的再平衡
[djm@hadoop102 hadoop-2.7.2]$ start-balancer.sh
創建白名單
[djm@hadoop101 hadoop]$ touch whitelist
配置加入黑名單的主機
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 節點
[djm@hadoop102 hadoop-2.7.2]$ yarn rmadmin -refreshNodes
如果數據不均衡,可以用命令實現集群的再平衡
[djm@hadoop102 hadoop-2.7.2]$ start-balancer.sh
黑白名單的區別:
白名單比較嚴格,黑名單比較平緩,處于黑名單中的主機會同步數據結束后繼續處于集群,只是不在處理請求而已,而不處于白名單中的主機會直接被干掉。
DataNode也可以配置成多個目錄,每個目錄存儲的數據不一樣,即:數據不是副本。
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>
采用 distcp 命令實現兩個 Hadoop 集群之間的遞歸數據復制
[djm@hadoop102 hadoop-2.7.2]$ hadoop distcp hdfs://haoop102:9000/user/djm/hello.txt hdfs://hadoop103:9000/user/djm/hello.txt
歸檔文件
[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>
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。