題記:正值學校運動會假期,想吸收點新鮮的血液。心血來潮搭了個hadoop的偽分布式,了解了下HDFS。
HDFS簡介
HDFS是Hadoop Distributed File System的簡稱,即hadoop分布式文件系統。它是Hadoop的核心組件,在最底層保存數據,為hadoop其他組件提供海量數據的數據的存儲和讀寫服務。而Hadoop的另一個核心即MapReduce則是基于HDFS對數據進行調度和分布式計算,這種計算可以理解為常用的讀取,刪除等處理的操作。原理是由MapReduce的JobTracker節點將計算任務(Job)分成幾個Task,每個task為一個子任務,從而對HDFS的分布式數據進行操作。HDFS的特點就是適合存儲超大的數據,適式數據的訪問,一次寫入,多次讀寫。但是HDFS也有短板:訪問的數據沒有實時性,由于其對大數據的吞吐量做了優化,所以不適合對數據的實時性訪問的場景,并且HDFS不支持并發寫,即對文件分片后只能一個塊一個塊的寫。而且Hadoop的權限管理也是一個問題,但是聽說可以結合kerberos解決。在hadoop1.0里面對文件也不能追加寫…2.0里面可以。。。
hadoop1.0和2.0的HDFS組件有些變化,需要注意的就是塊的大小由64MB變為128MB,并且在HDFS的2.0集群中,沒有secondaryNameNode。因為NameNode中的鏡像文件和內存中的原數據是實時同步的。所以不需要secondaryNameNode來對NameNode的FSImage和Edits文件進行切換,下載,合并,推送過程。這個之后再提。
我下載的是hadoop的1.2.1版本,目前就安裝它吧!
hadoop 1.0偽分布式搭建
hadoop安裝步驟:
- 安裝JDK:apt-get install openjdk-7-jdk;
- 設置環境變量:JAVA_HOME、JRE_HOME、CLASSPATH、PATH
- 下載hadoop安裝包并解壓到指定目錄下;
- 設置環境變量:HADOOP_HOME、PATH
- 修改相關配置文件$HADOOP_HOME/conf:
- 修改hadoop-env.sh,設置JAVA_HOME;
- 修改core-site.xml,設置hadoop.tmp.dir、dfs.name.dir、fs.default.name;
- 修改mapred-site.xml,設置mapred.job.tracker;
- 修改hdfs-site.xml,設置dfs.data.dir;
- 格式化:hadoop namenode -format;
- 啟動:start-all.sh
- 檢查:jps
完成的環境:
zhxfei@zhxfei-vm:~$ uname -a
Linux zhxfei-vm 4.2.0-27-generic #32~14.04.1-Ubuntu SMP Fri Jan 22 15:32:26 UTC 2016 x86_64 x86_64 x86_64 GNU/Linux
環境變量配置文件:
zhxfei@zhxfei-vm:~$ vim /etc/profile
# /etc/profile: system-wide .profile file for the Bourne shell (sh(1))
# and Bourne compatible shells (bash(1), ksh(1), ash(1), ...).
export JAVA_HOME=/usr/lib/jvm/java-7-openjdk-amd64
export JRE_HOME=$JAVA_HOME/jre
export HADOOP_HOME=/opt/hadoop-1.2.1/
export CLASSPATH=$JAVA_HOME/lib:$JRE_HOME/lib:$CLASSPATH
export PATH=$JAVA_HOME/bin:$JRE_HOME/bin:$HADOOP_HOME/bin:$PATH
export HADOOP_HOME_WARN_SUPPRESS=1 #在執行啟動腳本時會有個WRNING ,說Hadoop什么被抑制,添加此條就行
Hadoop的配置文件:
root@zhxfei-vm:/opt/hadoop-1.2.1/conf# vim core-site.xml
<?xml version="1.0"?>
<?xml-stylesheet type="text/xsl" href="configuration.xsl"?>
<!-- Put site-specific property overrides in this file. -->
<configuration>
<property>
<name>hadoop.tmp.dir</name>
<value>/hadoop</value>
</property>
<property>
<name>dfs.name.dir</name>
<value>/hadoop/name</value>
</property>
<property>
<name>fs.default.name</name>
<value>hdfs://zhxfei-vm:9000</value>
</property>
</configuration>
HDFS的配置文件
root@zhxfei-vm:/opt/hadoop-1.2.1/conf# vim hdfs-site.xml
<?xml version="1.0"?>
<?xml-stylesheet type="text/xsl" href="configuration.xsl"?>
<!-- Put site-specific property overrides in this file. -->
<configuration>
<property>
<name>dfs.data.dir</name>
<value>/hadoop/data</value>
</property>
</configuration>
MR的配置文件
root@zhxfei-vm:/opt/hadoop-1.2.1/conf# vim mapred-site.xml
<?xml version="1.0"?>
<?xml-stylesheet type="text/xsl" href="configuration.xsl"?>
<!-- Put site-specific property overrides in this file. -->
<configuration>
<property>
<name>mapred.job.tracker</name>
<value>zhxfei-vm:9001</value>
</property>
</configuration>
給hadoop設置JAVA_HOME環境變量
root@zhxfei-vm:/opt/hadoop-1.2.1/conf# vim hadoop-env.sh
# Set Hadoop-specific environment variables here.
# The only required environment variable is JAVA_HOME. All others are
# optional. When running a distributed configuration it is best to
# set JAVA_HOME in this file, so that it is correctly defined on
# remote nodes.
# The java implementation to use. Required.
export JAVA_HOME=/usr/lib/jvm/java-7-openjdk-amd64
如果沒有SSHD服務的話需自己安裝openssh-server的,在啟動Hadoop的時候需要與其進行連接時需要ssh協議的支持。安裝之后可以查看22端口是否開放,開放之后配置ssh免登陸
生成ssh免登陸密鑰, 執行完這個命令后,會生成兩個文件id_rsa(私鑰)、id_rsa.pub(公鑰)將公鑰拷貝到要免登陸的機器上,由于搭建的是偽分布式所以直接在本地:
ssh-keygen -t rsa
cat ~/.ssh/id_rsa.pub >> ~/.ssh/authorized_keys
之后如果發現不能啟動的話可以檢查iptables是否放行22端口。
安裝錯誤主要靠錯誤信息進行排錯,對了記得刷新配置:sourse /etc/profile
安裝完成之后可以用hadoop的啟動腳本 start-all.sh,執行之后使用java的jps查看hadoop是否正常運行NameNode,SecondaryNameNode,DataNode,JobTracker,TaskTracker是否正常運行即可
。操作如下:
root@zhxfei-vm:/opt/hadoop-1.2.1/conf$ start-all.sh
starting namenode, logging to /opt/hadoop-1.2.1/libexec/../logs/hadoop-root-namenode-zhxfei-vm.out
localhost: starting datanode, logging to /opt/hadoop-1.2.1/libexec/../logs/hadoop-root-datanode-zhxfei-vm.out
localhost: starting secondarynamenode, logging to /opt/hadoop-1.2.1/libexec/../logs/hadoop-root-secondarynamenode-zhxfei-vm.out
starting jobtracker, logging to /opt/hadoop-1.2.1/libexec/../logs/hadoop-root-jobtracker-zhxfei-vm.out
localhost: starting tasktracker, logging to /opt/hadoop-1.2.1/libexec/../logs/hadoop-root-tasktracker-zhxfei-vm.out
root@zhxfei-vm:/opt/hadoop-1.2.1/conf$ jps
15962 SecondaryNameNode
16202 TaskTracker
16252 Jps
15671 NameNode
16056 JobTracker
15819 DataNode
HDFS原理
HDFS的組成
在hadoop偽分布式環境中,SecondaryNameNode和NameNode還有DataNode是運行在一臺主機上的進程,用進程來模擬主機,而一個典型1.0版本的HDFS集群中,由一個namenode和一個secondarynode和至少一個Datanode,HDFS的客戶端數量沒有限制。所有數據都放置在DataNode進程的節點的Block(塊)里。但是在hadoop2.0集群中沒有SecondaryNameNode,但是在2.0的偽分布式模式中有SecondaryNameNode。
- Namenode:HDFS的大腦,接受client的操作請求,維護著整個HDFS系統的目錄樹,目錄里所有的文件和目錄,在內存中保留元數據信息,并將其以FSImage和命名空間鏡像的編輯日志保存在本地文件中,每次Namenode啟動默認加載最新的命名空間鏡像。內存和磁盤中各一份。
- FSImage:命名空間鏡像 /文件系統快照,為了防止NameNode所在機器掉電,HDFS的文件系統的目錄和元數據信息丟失而對HDFS的相關信息的鏡像備份。
- Edits:Edit Log記錄client對文件的操作而產生的元數據信息產生的變化。其保存的也是原數據信息,但是是更新的原數據信息。在SecondaryNameNode和NameNode進行交互后,會被清空。
- fstime:保存最近一次checkpoint的時間
以上這些文件是保存在linux的文件系統中。
SecoundaryNameNode:用于定期合并命名空間鏡像和對其的編輯日志。不是對NameNode的備份!
DataNode:數據節點。在NameNode的指導下完成I/O任務。所有HDFS的塊都存放在DataNode上,對于DataNode來說,塊就是一個普通的文件,hadoop1.0默認是64MB,而hadoop2.0默認是128MB。不同于普通文件系統的是,HDFS中,如果一個文件小于一個數據塊的大小,并不占用整個數據塊存儲空間
HDFS的客戶端:指用戶和HDFS交互的手段,有命令行接口,JAVA API,C語言庫,用戶空間文件系統等等
HDFS的塊
文件系統的塊大小只能是磁盤塊的整數倍,一般磁盤塊是512字節,而EXT3的文件系統的塊為4096,HDFS的文件塊大小為64MB,和其他文件系統不同的是HDFS小于一個塊大小不會占據整個塊的空間。塊的大小可以被改變,配置項為hdfs-site.xml中的dfs.block.size項,是datanode存儲數據的最小單元。
如下:
root@zhxfei-vm:/hadoop/data/current# ls
blk_3597001837970459933 blk_-3850128862716211144_2251.meta blk_-6524268894760927318 blk_-8587672643259394653_2242.meta
blk_3597001837970459933_2252.meta blk_-5563214751032658860 blk_-6524268894760927318_2250.meta dncp_block_verification.log.curr
blk_-3850128862716211144 blk_-5563214751032658860_2253.meta blk_-8587672643259394653 VERSION
HDFS的塊大小這么大是為了最小化尋址開銷,如果塊設置的足夠大,從磁盤傳輸的數據的時間明顯大于定位這個塊開始的時間。這樣傳輸一個由多個塊組成的文件的時間取決于磁盤傳輸的效率。但是設置的太大的話也不好,太大的話,因為當Job通過MapReduce分成子任務時如果子任務的數量受到預處理的文件的塊的數量限制。只有在適量的時候,才嗯那個發揮增加文件系統對高數據的吞吐量。hdfs-site.xml中還可以設置dfs.relication,配置每個HDFS的塊在Hadoop集群中保存的份數,默認為3,如果為3的話,Hadoop的默認布局會在HDFS的客戶端盡量放置第一個副本,如果客戶端在集群之外,則會避免存儲太滿并隨機選取一個節點放置。第二個副本放置在隨機選擇的另一個機架上的任意DataNode,第三各副本放置在和第二個副本相同機架隨機的另一個不同的DataNode上。這樣可以提供很好的數據的冗余性。
元數據存儲細節
Metadata(Filename,reliacas,block-ids,id2host……)
對應著:Metadata(/test/a.log,3,{blk_1,blk_2},[{blk_1:[h1,h2,h3]},{blk_2:[h0,h2,h3]}],……)
表示著:/test/a.log一共有3個副本,被分成2個block塊,第一個塊的三個副本在h1,h2,h3中存放,第二個塊在h0,h2,h3中存放。
當client在NameNode拿到元數據信息之后,其會根據就近原則去取塊。每個塊采用了CRC校驗機制,如果出現問題或者校驗出錯不符合則換塊讀取,NameNode在收到client的反饋會通知DataNode根據pipeline對那個損壞的塊進行重新的備份。
NameNode和SecondaryNameNode
NameNode的工作特點:Namenode始終在內存中保存metedata,用于處理“讀請求”
到有“寫請求”到來時,namenode會首先寫editlog到磁盤,即向edits文件中寫日志,成功返回后,才會修改內存,并且向客戶端返回
Hadoop會維護一個fsimage文件,也就是namenode中metedata的鏡像,但是fsimage不會隨時與namenode內存中的metedata保持一致,而是每隔一段時間通過合并edits文件來更新內容。Secondary namenode就是用來合并fsimage和edits文件來更新NameNode的metedata的。SecondaryNameNode的工作特點,HA的一個解決方案。但不支持熱備。配置即可。執行過程:從NameNode上通過HTTP協議下載元數據信息(fsimage,edits),然后把二者合并,生成新的fsimage,在本地保存,并將其推送到NameNode,替換舊的fsimage.默認在安裝在NameNode節點上
其交互如下:
1.SecondaryNameNode引導NameNode切換Edit Log文件,生成Edit Log.New并開始更新新的內容寫進Edit Log.New
2.SecondaryNameNode將NameNode的FSImage和Edit Log文件復制到本地的檢查點目錄。
3.SecondaryNameNode載入FSImage文件,回放Edit Log文件將其合并FSImage,并將新的FSImage文件壓縮后寫入磁盤。
4.SecondaryNameNode將新的FSImage文件送回到NameNode,NameNode在接受新的FSImage后直接加載和應用該文件,將舊的FSImage和Edit Log文件刪除,并將Edit log.New其更名為Edit Log。
這個過程每個小時即3600s發生一次,或者當超過fs.checkpoint.size即 規定edits文件的最大值則強制checkpoint,不管是否到達最大時間間隔。默認大小是64M。
HDFS的容錯機制:
心跳機制:NameNode和DataNode之間維持心跳檢測,當由于網絡故障之類的原因,導致DataNode發出的心跳包沒有被NameNode正常收到時,NameNode不會給那個DataNode分配新的I/O操作并認為那個DataNode上的數據為無效的。因此NameNode會檢測文件塊的副本數目小于設置的值,若小于則開始自動復制新的副本并分發給其他的DataNode上檢測文件塊的完整性:HDFS會記錄每個新建文件的所有塊校驗和,當以后在檢索這些文件的時候或者從某個節點獲取塊的時候首先確認校驗和是否一致,若不一致則去其他的DataNode中獲取該塊的副本。
集群的負載均衡:當某個DataNode的空閑大于一個臨界值的時候HDFS會從其他DataNode遷移數據過來文件的刪除:刪除并不是從NameNode中移除命名空間,而是存放在/trash目錄中可以隨時恢復,直到 hdfs-site.xml 中的配置時間 fs.trash.interval決定,單位為s
HDFS簡單操作
Web UI
自Firefox中訪問虛擬機的地址和對應的端口號。50070為默認的namenode的端口,50030為默認的jobtracker的端口
HDFS shell
感覺和linux差不多,略過