[TOC]
# 命令行
HDFS命令行客戶端使用
HDFS提供shell命令行客戶端,使用方法如下:
可以使用一下兩種形式:
~~~
hadoop fs -… <args>
hdfs dfs -… <args>
~~~
## 命令行參數
~~~
[-appendToFile <localsrc> ... <dst>]
[-cat [-ignoreCrc] <src> ...]
[-checksum <src> ...]
[-chgrp [-R] GROUP PATH...]
[-chmod [-R] <MODE[,MODE]... | OCTALMODE> PATH...]
[-chown [-R] [OWNER][:[GROUP]] PATH...]
[-copyFromLocal [-f] [-p] <localsrc> ... <dst>]
[-copyToLocal [-p] [-ignoreCrc] [-crc] <src> ... <localdst>]
[-count [-q] <path> ...]
[-cp [-f] [-p] <src> ... <dst>]
[-createSnapshot <snapshotDir> [<snapshotName>]]
[-deleteSnapshot <snapshotDir> <snapshotName>]
[-df [-h] [<path> ...]]
[-du [-s] [-h] <path> ...]
[-expunge]
[-get [-p] [-ignoreCrc] [-crc] <src> ... <localdst>]
[-getfacl [-R] <path>]
[-getmerge [-nl] <src> <localdst>]
[-help [cmd ...]]
[-ls [-d] [-h] [-R] [<path> ...]]
[-mkdir [-p] <path> ...]
[-moveFromLocal <localsrc> ... <dst>]
[-moveToLocal <src> <localdst>]
[-mv <src> ... <dst>]
[-put [-f] [-p] <localsrc> ... <dst>]
[-renameSnapshot <snapshotDir> <oldName> <newName>]
[-rm [-f] [-r|-R] [-skipTrash] <src> ...]
[-rmdir [--ignore-fail-on-non-empty] <dir> ...]
[-setfacl [-R] [{-b|-k} {-m|-x <acl_spec>} <path>]|[--set <acl_spec> <path>]]
[-setrep [-R] [-w] <rep> <path> ...]
[-stat [format] <path> ...]
[-tail [-f] <file>]
[-test -[defsz] <path>]
[-text [-ignoreCrc] <src> ...]
[-touchz <path> ...]
[-usage [cmd ...]]
~~~
## 常用命令行參數介紹
### 查
~~~
-help
功能:輸出這個命令參數手冊
~~~
~~~
-ls
功能:顯示目錄信息
示例: hadoop fs -ls hdfs://hadoop-server01:9000/
備注:這些參數中,所有的hdfs路徑都可以簡寫
-->hadoop fs -ls / 等同于上一條命令的效果
~~~
~~~
-cat
功能:顯示文件內容
hadoop fs -cat /hello.txt
~~~
~~~
-tail
功能:顯示一個文件的末尾
hadoop fs -tail /weblog/access_log.1
~~~
~~~
-text
功能:以字符形式打印一個文件的內容
hadoop fs -text /weblog/access_log.1
~~~
~~~
-df
功能:統計文件系統的可用空間信息
hadoop fs -df -h /
-du
功能:統計文件夾的大小信息
hadoop fs -du -s -h /aaa/*
-count
功能:統計一個指定目錄下的文件節點數量
hadoop fs -count /aaa/
~~~
~~~
hdfs dfsadmin -report
查看dfs集群工作狀態的命令
~~~
### 增
~~~
-mkdir
功能:在hdfs上創建目錄
hadoop fs -mkdir -p /aaa/bbb/cc/dd
~~~
~~~
-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
~~~
~~~
-get
功能:等同于copyToLocal,就是從hdfs下載文件到本地
hadoop fs -get /aaa/jdk.tar.gz
~~~
~~~
-getmerge
功能:合并下載多個文件
比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
~~~
### 改
~~~
--appendToFile
功能:追加一個文件到已經存在的文件末尾
hadoop fs -appendToFile ./hello.txt hdfs://hadoop-server01:9000/hello.txt
可以簡寫為:
Hadoop fs -appendToFile ./hello.txt /hello.txt
~~~
~~~
-chgrp
-chmod
-chown
功能:linux文件系統中的用法一樣,對文件所屬權限
hadoop fs -chmod 666 /hello.txt
hadoop fs -chown someuser:somegrp /hello.txt
hadoop fs -ls / 這個查權限,權限所屬者是linux上的用戶,組是hadoop中的
~~~
~~~
-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
~~~
~~~
-mv
功能:在hdfs目錄中移動文件
hadoop fs -mv /aaa/jdk.tar.gz /
~~~
~~~
-setrep
功能:設置hdfs中文件的副本數量
hadoop fs -setrep 3 /aaa/jdk.tar.gz
~~~
### 刪
~~~
-rm
功能:刪除文件或文件夾
hadoop fs -rm -r /aaa/bbb/
-rmdir
功能:刪除空目錄
hadoop fs -rmdir /aaa/bbb/ccc
~~~
# 概述
1. HDFS集群分為兩大角色:NameNode、DataNode (Secondary Namenode)
2. NameNode負責管理整個文件系統的元數據
3. DataNode 負責管理用戶的文件數據塊
4. 文件會按照固定的大小(blocksize)切成若干塊后分布式存儲在若干臺datanode上
5. 每一個文件塊可以有多個副本,并存放在不同的datanode上
6. Datanode會定期向Namenode匯報自身所保存的文件block信息,而namenode則會負責保持文件的副本數量
7. 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并在客戶端本地進行數據追加合并從而獲得整個文件
### HDFS讀數據流程
客戶端將要讀取的文件路徑發送給namenode,namenode獲取文件的元信息(主要是block的存放位置信息)返回給客戶端,客戶端根據返回的信息找到相應datanode逐個獲取文件的block并在客戶端本地進行數據追加合并從而獲得整個文件

有時候會發現有crc文件,這是校驗文件,校驗讀取的文件是不是完整的
詳細步驟解析
1. 跟namenode通信查詢元數據,找到文件塊所在的datanode服務器
2. 挑選一臺datanode(就近原則,然后隨機)服務器,請求建立socket流
3. datanode開始發送數據(從磁盤里面讀取數據放入流,以packet為單位來做校驗)
4. 客戶端以packet為單位接收,現在本地緩存,然后寫入目標文件
# NAMENODE工作機制
## 問題場景:
1. 集群啟動后,可以查看目錄,但是上傳文件時報錯,打開web頁面可看到namenode正處于safemode狀態,怎么處理?
解釋:
safemode是namenode的一種狀態(active/standby/safemode安全模式)
namenode進入安全模式的原理:
a. namenode發現集群中的block丟失率達到一定比例時(0.01%),namenode就會進入安全模式,在安全模式下,客戶端不能對任何數據進行操作,只能查看元數據信息(比如ls/mkdir)
b. 如何退出安全模式?
找到問題所在,進行修復(比如修復宕機的datanode)
或者可以手動強行退出安全模式(沒有真正解決問題): `hdfs namenode --safemode leave`
c. 在hdfs集群正常冷啟動時,namenode也會在safemode狀態下維持相當長的一段時間,此時你不需要去理會,等待它自動退出安全模式即可
(原理:
namenode的內存元數據中,包含文件路徑、副本數、blockid,及每一個block所在datanode的信息,而fsimage中,不包含block所在的datanode信息,那么,當namenode冷啟動時,此時內存中的元數據只能從fsimage中加載而來,從而就沒有block所在的datanode信息——>就會導致namenode認為所有的block都已經丟失——>進入安全模式——>datanode啟動后,會定期向namenode匯報自身所持有的blockid信息,——>隨著datanode陸續啟動,從而陸續匯報block信息,namenode就會將內存元數據中的block所在datanode信息補全更新——>找到了所有block的位置,從而自動退出安全模式)
2. Namenode服務器的磁盤故障導致namenode宕機,如何挽救集群及數據?
解決:
namenode配置多個路徑,也可以用網絡磁盤路徑
secondary namenode的目錄可以恢復
3. Namenode是否可以有多個?namenode內存要配置多大?namenode跟集群數據存儲能力有關系嗎?
解決:
可以多個
內存一般配置幾十G就行
跟集群存儲關系不是很大,和datanode有關,當然了要避免上傳小文件
4. 文件的blocksize究竟調大好還是調小好?--結合mapreduce
要看數據量和業務邏輯
最好mapreduce跑了不要太長
## NAMENODE職責
負責客戶端請求的響應
元數據的管理(查詢,修改)
## 元數據管理
namenode對數據的管理采用了三種存儲形式:
1. 內存元數據(NameSystem)(namenode自己封裝一個文件系統)
2. 磁盤元數據鏡像文件
3. 數據操作日志文件(可通過日志運算出元數據)
### 元數據存儲機制
A. 內存中有一份完整的元數據(內存meta data) (內存meta data = fsimage + edits文件)
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的元數據
**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 $HADOOP_CONF_DIR? -upgrade -clusterId <cluster_ID>
~~~
如果沒有提供ClusterID,則會自動生成一個ClusterID。
(6). blockpoolID:是針對每一個Namespace所對應的blockpool的ID,上面的這個BP-893790215-192.168.24.72-1383809616115就是在我的ns1的namespace下的存儲塊池的ID,這個ID包括了其對應的NameNode節點的ip地址。
2. ` $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
# DATANODE的工作機制
## 問題場景
1. 集群容量不夠,怎么擴容?
2. 如果有一些datanode宕機,該怎么辦?
3. datanode明明已啟動,但是集群中的可用datanode列表中就是沒有,怎么辦?
以上這類問題的解答,有賴于對datanode工作機制的深刻理解
## 概述
### Datanode工作職責:
1. 存儲管理用戶的文件塊數據
定期向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>
~~~
## 觀察驗證DATANODE功能
上傳一個文件,觀察文件的block具體的物理存放情況:
在每一臺datanode機器上的這個目錄中能找到文件的切塊:
~~~
/home/hadoop/app/hadoop-2.4.1/tmp/dfs/data/current/BP-193442119-192.168.2.120-1432457733977/current/finalized
~~~
- linux
- 常用命令
- 高級文本命令
- 面試題
- redis
- String
- list
- hash
- set
- sortedSet
- 案例-推薦
- java高級特性
- 多線程
- 實現線程的三種方式
- 同步關鍵詞
- 讀寫鎖
- 鎖的相關概念
- 多線程的join
- 有三個線程T1 T2 T3,保證順序執行
- java五種線程池
- 守護線程與普通線程
- ThreadLocal
- BlockingQueue消息隊列
- JMS
- 反射
- volatile
- jvm
- IO
- nio
- netty
- netty簡介
- 案例一發送字符串
- 案例二發送對象
- 輕量級RPC開發
- 簡介
- spring(IOC/AOP)
- spring初始化順序
- 通過ApplicationContextAware加載Spring上下文
- InitializingBean的作用
- 結論
- 自定義注解
- zk在框架中的應用
- hadoop
- 簡介
- hadoop集群搭建
- hadoop單機安裝
- HDFS簡介
- hdfs基本操作
- hdfs環境搭建
- 常見問題匯總
- hdfs客戶端操作
- mapreduce工作機制
- 案列-單詞統計
- 局部聚合Combiner
- 案列-流量統計(分區,排序,比較)
- 案列-倒排索引
- 案例-共同好友
- 案列-join算法實現
- 案例-求topN(分組)
- 自定義inputFormat
- 自定義outputFormat
- 框架運算全流程
- mapreduce的優化方案
- HA機制
- Hive
- 安裝
- DDL操作
- 創建表
- 修改表
- DML操作
- Load
- insert
- select
- join操作
- 嚴格模式
- 數據類型
- shell參數
- 函數
- 內置運算符
- 內置函數
- 自定義函數
- Transform實現
- 特殊分割符處理
- 案例
- 級聯求和accumulate
- flume
- 簡介
- 安裝
- 常用的組件
- 攔截器
- 案例
- 采集目錄到HDFS
- 采集文件到HDFS
- 多個agent串聯
- 日志采集和匯總
- 自定義攔截器
- 高可用配置
- 使用注意
- sqoop
- 安裝
- 數據導入
- 導入數據到HDFS
- 導入關系表到HIVE
- 導入表數據子集
- 增量導入
- 數據導出
- 作業
- 原理
- azkaban
- 簡介
- 安裝
- 案例
- 簡介
- command類型單一job
- command類型多job工作流flow
- HDFS操作任務
- mapreduce任務
- hive腳本任務
- hbase
- 簡介
- 安裝
- 命令行
- 基本CURD
- 過濾器查詢
- 系統架構
- 物理存儲
- 尋址機制
- 讀寫過程
- Region管理
- master工作機制
- 建表高級屬性
- 與mapreduce結合
- 協處理器
- 點擊流平臺開發
- 簡介
- storm
- 簡介
- 安裝
- 集群啟動及任務過程分析
- 單詞統計
- 并行度
- ACK容錯機制
- ACK簡介