HDFS前言
l 設計思想
分而治之:將大文件、大批量文件,分佈式存放在大量服務器上,以便於採取分而治之的方式對海量數據進行運算分析;
l 在大數據系統中作用:
爲各類分佈式運算框架(如:mapreduce,spark,tez,……)提供數據存儲服務
l 重點概念:文件切塊,副本存放,元數據
HDFS的概念和特性
首先,它是一個文件系統,用於存儲文件,通過統一的命名空間——目錄樹來定位文件
其次,它是分佈式的,由很多服務器聯合起來實現其功能,集羣中的服務器有各自的角色;
重要特性如下:
(1)HDFS中的文件在物理上是分塊存儲(block),塊的大小可以通過配置參數( dfs.blocksize)來規定,默認大小在hadoop2.x版本中是128M,老版本中是64M
(2)HDFS文件系統會給客戶端提供一個統一的抽象目錄樹,客戶端通過路徑來訪問文件,形如:hdfs://namenode:port/dir-a/dir-b/dir-c/file.data
(3)目錄結構及文件分塊信息(元數據)的管理由namenode節點承擔
——namenode是HDFS集羣主節點,負責維護整個hdfs文件系統的目錄樹,以及每一個路徑(文件)所對應的block塊信息(block的id,及所在的datanode服務器)
(4)文件的各個block的存儲管理由datanode節點承擔
---- datanode是HDFS集羣從節點,每一個block都可以在多個datanode上存儲多個副本(副本數量也可以通過參數設置dfs.replication)
(5)HDFS是設計成適應一次寫入,多次讀出的場景,且不支持文件的修改
HDFS的shell(命令行客戶端)操作
HDFS命令行客戶端使用
HDFS提供shell命令行客戶端,使用方法如下:
命令行客戶端支持的命令參數
[-appendToFile … ]
[-cat [-ignoreCrc] …]
[-checksum …]
[-chgrp [-R] GROUP PATH…]
[-chmod [-R] <MODE[,MODE]… | OCTALMODE> PATH…]
[-chown [-R] [OWNER][:[GROUP]] PATH…]
[-copyFromLocal [-f] [-p] … ]
[-copyToLocal [-p] [-ignoreCrc] [-crc] … ]
[-count [-q]
[-cp [-f] [-p] … ]
[-createSnapshot []]
[-deleteSnapshot ]
[-df [-h] [
[-du [-s] [-h]
[-expunge]
[-get [-p] [-ignoreCrc] [-crc] … ]
[-getfacl [-R]
[-getmerge [-nl] ]
[-help [cmd …]]
[-ls [-d] [-h] [-R] [
[-mkdir [-p]
[-moveFromLocal … ]
[-moveToLocal ]
[-mv … ]
[-put [-f] [-p] … ]
[-renameSnapshot ]
[-rm [-f] [-r|-R] [-skipTrash] …]
[-rmdir [–ignore-fail-on-non-empty]
[-setfacl [-R] [{-b|-k} {-m|-x <acl_spec>}
[-setrep [-R] [-w]
[-stat [format]
[-tail [-f] ]
[-test -[defsz]
[-text [-ignoreCrc] …]
[-touchz
[-usage [cmd …]]
常用命令參數介紹
命令 | 功能 | 例子 | 備註 |
---|---|---|---|
-help | 輸出這個命令參數手冊 | ||
-ls | 顯示目錄信息 | hadoop fs -ls hdfs://hadoop-server01:9000/ | 這些參數中,所有的hdfs路徑都可以簡寫 hadoop fs -ls / 等同於上一條命令的效果 |
-mkdir | 在hdfs上創建目錄 | hadoop fs -mkdir -p /aaa/bbb/cc/dd | |
-moveFromLocal | 從本地剪切粘貼到hdfs | hadoop fs - moveFromLocal /home/hadoop/a.txt /aaa/bbb/cc/dd | |
-moveToLocal | 從hdfs剪切粘貼到本地 | hadoop fs - moveToLocal /aaa/bbb/cc/dd /home/hadoop/a.txt | |
–appendToFile | 追加一個文件到已經存在的文件末尾 | hadoop fs -appendToFile ./hello.txt hdfs://hadoop-server01:9000/hello.txt | Hadoop fs -appendToFile ./hello.txt /hello.txt |
-cat | 顯示文件內容 | hadoop fs -cat /hello.txt | |
-tail | 顯示一個文件的末尾 | hadoop fs -tail /weblog/access_log.1 | |
-text | 以字符形式打印一個文件的內容 | hadoop fs -text /weblog/access_log.1 | |
-chgrp -chmod -chown | linux文件系統中的用法一樣,對文件所屬權限 | hadoop fs -chmod 666 /hello.txt | hadoop fs -chown someuser:somegrp /hello.txt |
-copyFromLocal | 從本地文件系統中拷貝文件到hdfs路徑去 | hadoop fs -copyFromLocal ./jdk.tar.gz /aaa/ | |
-copyToLocal | 從hdfs拷貝到本地 | hadoop fs -copyToLocal /aaa/jdk.tar.gz | |
-cp | 從hdfs的一個路徑拷貝hdfs的另一個路徑 | hadoop fs -cp /aaa/jdk.tar.gz /bbb/jdk.tar.gz.2 | |
-mv | 在hdfs目錄中移動文件 | hadoop fs -mv /aaa/jdk.tar.gz / | |
-get | 等同於copyToLocal,就是從hdfs下載文件到本地 | hadoop fs -get /aaa/jdk.tar.gz | |
-getmerge | 合併下載多個文件 | 比如hdfs的目錄 /aaa/下有多個文件:log.1, log.2,log.3,…hadoop fs -getmerge /aaa/log.* ./log.sum | |
-put | 等同於copyFromLocal | hadoop fs -put /aaa/jdk.tar.gz /bbb/jdk.tar.gz.2 | |
-rm | 刪除文件或文件夾 | hadoop fs -rm -r /aaa/bbb/ | |
-rmdir | 刪除空目錄 | hadoop fs -rmdir /aaa/bbb/ccc | |
-df | 統計文件系統的可用空間信息 | hadoop fs -df -h / | |
-du | 統計文件夾的大小信息 | hadoop fs -du -s -h /aaa/* | |
-count | 統計一個指定目錄下的文件節點數量 | hadoop fs -count /aaa/ | |
-setrep | 設置hdfs中文件的副本數量 | hadoop fs -setrep 3 /aaa/jdk.tar.gz |
HDFS原理
概述
- HDFS集羣分爲兩大角色:NameNode、DataNode (Secondary Namenode)
- NameNode負責管理整個文件系統的元數據
- DataNode 負責管理用戶的文件數據塊
- 文件會按照固定的大小(blocksize)切成若干塊後分布式存儲在若干臺datanode上
- 每一個文件塊可以有多個副本,並存放在不同的datanode上
- Datanode會定期向Namenode彙報自身所保存的文件block信息,而namenode則會負責保持文件的副本數量
- HDFS的內部工作機制對客戶端保持透明,客戶端請求訪問HDFS都是通過向namenode申請來進行
HDFS寫數據流程
概述
客戶端要向HDFS寫數據,首先要跟namenode通信以確認可以寫文件並獲得接收文件block的datanode,然後,客戶端按順序將文件逐個block傳遞給相應datanode,並由接收到block的datanode負責向其他datanode複製block的副本
詳細步驟圖
詳細步驟解析
1、根namenode通信請求上傳文件,namenode檢查目標文件是否已存在,父目錄是否存在
2、namenode返回是否可以上傳
3、client請求第一個 block該傳輸到哪些datanode服務器上
4、namenode返回3個datanode服務器ABC
5、client請求3臺dn中的一臺A上傳數據(本質上是一個RPC調用,建立pipeline),A收到請求會繼續調用B,然後B調用C,將真個pipeline建立完成,逐級返回客戶端
6、client開始往A上傳第一個block(先從磁盤讀取數據放到一個本地內存緩存),以packet爲單位,A收到一個packet就會傳給B,B傳給C;A每傳一個packet會放入一個應答隊列等待應答
7、當一個block傳輸完成之後,client再次請求namenode上傳第二個block的服務器。
HDFS讀數據流程
概述
客戶端將要讀取的文件路徑發送給namenode,namenode獲取文件的元信息(主要是block的存放位置信息)返回給客戶端,客戶端根據返回的信息找到相應datanode逐個獲取文件的block並在客戶端本地進行數據追加合併從而獲得整個文件
詳細步驟圖
詳細步驟解析
1、跟namenode通信查詢元數據,找到文件塊所在的datanode服務器
2、挑選一臺datanode(就近原則,然後隨機)服務器,請求建立socket流
3、datanode開始發送數據(從磁盤裏面讀取數據放入流,以packet爲單位來做校驗)
4、客戶端以packet爲單位接收,現在本地緩存,然後寫入目標文件
NAMENODE工作機制
NAMENODE職責
NAMENODE職責:
負責客戶端請求的響應
元數據的管理(查詢,修改)
元數據管理
namenode對數據的管理採用了三種存儲形式:
內存元數據(NameSystem)
磁盤元數據鏡像文件
數據操作日誌文件(可通過日誌運算出元數據)
元數據存儲機制
A、內存中有一份完整的元數據(內存meta data)
B、磁盤有一個“準完整”的元數據鏡像(fsimage)文件(在namenode的工作目錄中)
C、用於銜接內存metadata和持久化元數據鏡像fsimage之間的操作日誌(edits文件)注:當客戶端對hdfs中的文件進行新增或者修改操作,操作記錄首先被記入edits日誌文件中,當客戶端操作成功後,相應的元數據會更新到內存meta.data中
元數據手動查看
可以通過hdfs的一個工具來查看edits中的信息
bin/hdfs oev -i edits -o edits.xml
bin/hdfs oiv -i fsimage_0000000000000000087 -p XML -o fsimage.xml
元數據的checkpoint
每隔一段時間,會由secondary namenode將namenode上積累的所有edits和一個最新的fsimage下載到本地,並加載到內存進行merge(這個過程稱爲checkpoint)
checkpoint的詳細過程
checkpoint操作的觸發條件配置參數
dfs.namenode.checkpoint.check.period=60 #檢查觸發條件是否滿足的頻率,60秒
dfs.namenode.checkpoint.dir=file://${hadoop.tmp.dir}/dfs/namesecondary#以上兩個參數做checkpoint操作時,secondary namenode的本地工作目錄
dfs.namenode.checkpoint.edits.dir=${dfs.namenode.checkpoint.dir} dfs.namenode.checkpoint.max-retries=3 #最大重試次數
dfs.namenode.checkpoint.period=3600 #兩次checkpoint之間的時間間隔3600秒
dfs.namenode.checkpoint.txns=1000000 #兩次checkpoint之間最大的操作記錄
checkpoint的附帶作用
namenode和secondary namenode的工作目錄存儲結構完全相同,所以,當namenode故障退出需要重新恢復時,可以從secondary namenode的工作目錄中將fsimage拷貝到namenode的工作目錄,以恢復namenode的元數據
元數據目錄說明
在第一次部署好Hadoop集羣的時候,我們需要在NameNode(NN)節點上格式化磁盤:
$HADOOP_HOME/bin/hdfs namenode -format
格式化完成之後,將會在$dfs.namenode.name.dir/current目錄下如下的文件結構
current/
|-- VERSION
|-- edits_*
|-- fsimage_0000000000008547077
|-- fsimage_0000000000008547077.md5
`-- seen_txid
其中的dfs.name.dir是在hdfs-site.xml文件中配置的,默認值如下:
<property>
<name>dfs.name.dir</name>
<value>file://${hadoop.tmp.dir}/dfs/name</value>
</property>
hadoop.tmp.dir是在core-site.xml中配置的,默認值如下
<property>
<name>hadoop.tmp.dir</name>
<value>/tmp/hadoop-${user.name}</value>
<description>A base for other temporary directories.</description>
</property>
dfs.namenode.name.dir屬性可以配置多個目錄,
如/data1/dfs/name,/data2/dfs/name,/data3/dfs/name,…。各個目錄存儲的文件結構和內容都完全一樣,相當於備份,這樣做的好處是當其中一個目錄損壞了,也不會影響到Hadoop的元數據,特別是當其中一個目錄是NFS(網絡文件系統Network File System,NFS)之上,即使你這臺機器損壞了,元數據也得到保存。
下面對$dfs.namenode.name.dir/current/目錄下的文件進行解釋。
1、VERSION文件是Java屬性文件,內容大致如下:
#Fri Nov 15 19:47:46 CST 2013
namespaceID=934548976
clusterID=CID-cdff7d73-93cd-4783-9399-0a22e6dce196
cTime=0
storageType=NAME_NODE
blockpoolID=BP-893790215-192.168.24.72-1383809616115
layoutVersion=-47
其中
(1)、namespaceID是文件系統的唯一標識符,在文件系統首次格式化之後生成的;
(2)、storageType說明這個文件存儲的是什麼進程的數據結構信息(如果是DataNode,storageType=DATA_NODE);
(3)、cTime表示NameNode存儲時間的創建時間,由於我的NameNode沒有更新過,所以這裏的記錄值爲0,以後對NameNode升級之後,cTime將會記錄更新時間戳;
(4)、layoutVersion表示HDFS永久性數據結構的版本信息, 只要數據結構變更,版本號也要遞減,此時的HDFS也需要升級,否則磁盤仍舊是使用舊版本的數據結構,這會導致新版本的NameNode無法使用;
(5)、clusterID是系統生成或手動指定的集羣ID,在-clusterid選項中可以使用它;如下說明
a、使用如下命令格式化一個Namenode:
$HADOOP_HOME/bin/hdfs namenode -format [-clusterId <cluster_id>]
選擇一個唯一的cluster_id,並且這個cluster_id不能與環境中其他集羣有衝突。如果沒有提供cluster_id,則會自動生成一個唯一的ClusterID。
b、使用如下命令格式化其他Namenode:
$HADOOP_HOME/bin/hdfs namenode -format -clusterId <cluster_id>
c、升級集羣至最新版本。在升級過程中需要提供一個ClusterID,例如:
$HADOOP_PREFIX_HOME/bin/hdfs start namenode --config dfs.namenode.name.dir/current/seen_txid非常重要,是存放transactionId的文件,format之後是0,它代表的是namenode裏面的edits_*文件的尾數,namenode重啓的時候,會按照seen_txid的數字,循序從頭跑edits_0000001~到seen_txid的數字。所以當你的hdfs發生異常重啓的時候,一定要比對seen_txid內的數字是不是你edits最後的尾數,不然會發生建置namenode時metaData的資料有缺少,導致誤刪Datanode上多餘Block的資訊。
3、$dfs.namenode.name.dir/current目錄下在format的同時也會生成fsimage和edits文件,及其對應的md5校驗文件。
補充:seen_txid
文件中記錄的是edits滾動的序號,每次重啓namenode時,namenode就知道要將哪些edits進行加載edits
DATANODE的工作機制
概述
1、Datanode工作職責:
存儲管理用戶的文件塊數據
定期向namenode彙報自身所持有的block信息(通過心跳信息上報)
(這點很重要,因爲,當集羣中發生某些block副本失效時,集羣如何恢復block初始副本數量的問題)
<property>
<name>dfs.blockreport.intervalMsec</name>
<value>3600000</value>
<description>Determines block reporting interval in milliseconds.</description>
</property>
2、Datanode掉線判斷時限參數
datanode進程死亡或者網絡故障造成datanode無法與namenode通信,namenode不會立即把該節點判定爲死亡,要經過一段時間,這段時間暫稱作超時時長。HDFS默認的超時時長爲10分鐘+30秒。如果定義超時時間爲timeout,則超時時長的計算公式爲:
timeout = 2 * heartbeat.recheck.interval + 10 * dfs.heartbeat.interval。
而默認的heartbeat.recheck.interval 大小爲5分鐘,dfs.heartbeat.interval默認爲3秒。
需要注意的是hdfs-site.xml 配置文件中的heartbeat.recheck.interval的單位爲毫秒,dfs.heartbeat.interval的單位爲秒。所以,舉個例子,如果heartbeat.recheck.interval設置爲5000(毫秒),dfs.heartbeat.interval設置爲3(秒,默認),則總的超時時間爲40秒。
<property>
<name>heartbeat.recheck.interval</name>
<value>2000</value>
</property>
<property>
<name>dfs.heartbeat.interval</name>
<value>1</value>
</property>