一、Hadoop概述
Hadoop是Google的集群系統(tǒng)開(kāi)源實(shí)現(xiàn)
Google的集群系統(tǒng):GFS、MapReduce、BigTable
Hadoop的集群系統(tǒng):HDFS、MapReduce、HBase
Hadoop設(shè)計(jì)的初衷是為了解決Nutch的海量數(shù)據(jù)存儲(chǔ)和處理的需求,可以解決大數(shù)據(jù)場(chǎng)景下的數(shù)據(jù)存儲(chǔ)和處理的問(wèn)題。
傳統(tǒng)數(shù)據(jù):GB、TB級(jí)別的數(shù)據(jù)、數(shù)據(jù)增長(zhǎng)不快、主要為結(jié)構(gòu)化的數(shù)據(jù)、統(tǒng)計(jì)和報(bào)表
大數(shù)據(jù):TB、PB級(jí)別的數(shù)據(jù)、持續(xù)的高速增長(zhǎng)、半結(jié)構(gòu)化、非結(jié)構(gòu)化的數(shù)據(jù)、數(shù)據(jù)挖掘和預(yù)測(cè)性分析、海量數(shù)據(jù)的獲取、存儲(chǔ)、聚合、管理這些數(shù)據(jù)以及對(duì)數(shù)據(jù)進(jìn)行深度分析的新技術(shù)和新能力。
**名字的起源: Doug Cutting如此解釋Hadoop的得名:"這個(gè)名字是我孩子給一頭吃飽了的棕黃色大象命名的。我的命名標(biāo)準(zhǔn)就是簡(jiǎn)短,容易發(fā)音和拼寫(xiě),沒(méi)有太多的意義,并且不會(huì)被用于別處。小孩子是這方面的高手。Googol就是由小孩命名的。"
組成:HDFS MapReduce Yarn
二、Hadoop版本 下載安裝
1.下載
下載地址:http://hadoop.apache.org/releases.html
**Apache Hadoop版本分為兩代,我們將第一代Hadoop稱(chēng)為Hadoop 1.0,第二代Hadoop稱(chēng)為Hadoop 2.0。第一代Hadoop包含三個(gè)大版本,分別是0.20.x,0.21.x和0.22.x,其中,0.20.x最后演化成1.0.x,變成了穩(wěn)定版,而0.21.x和0.22.x則NameNode HA等新的重大特性。第二代Hadoop包含兩個(gè)版本,分別是0.23.x和2.x,它們完全不同于Hadoop 1.0,是一套全新的架構(gòu),均包含HDFS Federation和YARN兩個(gè)系統(tǒng),相比于0.23.x,2.x增加了NameNode HA和Wire-compatibility兩個(gè)重大特性
2.安裝
Hadoop的安裝分為單機(jī)方式、偽分布式方式 和 完全分布式方式。
單機(jī)模式是Hadoop的默認(rèn)模式。當(dāng)首次解壓Hadoop的源碼包時(shí),Hadoop無(wú)法了解硬件安裝環(huán)境,便保守地選擇了最小配置。在這種默認(rèn)模式下所有3個(gè)XML文件均為空。當(dāng)配置文件為空時(shí),Hadoop會(huì)完全運(yùn)行在本地。因?yàn)椴恍枰c其他節(jié)點(diǎn)交互,單機(jī)模式就不使用HDFS,也不加載任何Hadoop的守護(hù)進(jìn)程。該模式主要用于開(kāi)發(fā)調(diào)試MapReduce程序的應(yīng)用邏輯。
偽分布模式:Hadoop守護(hù)進(jìn)程運(yùn)行在本地機(jī)器上,模擬一個(gè)小規(guī)模的的集群??梢允褂肏DFS和MapReduce
全分布模式:Hadoop守護(hù)進(jìn)程運(yùn)行在一個(gè)集群上
二、HDFS的特點(diǎn)
1.HDFS概述(HDFS架構(gòu)圖):

HDFS為了保證數(shù)據(jù)存儲(chǔ)的可靠性和讀取性能,對(duì)數(shù)據(jù)進(jìn)行切塊后進(jìn)行復(fù)制并存儲(chǔ)在集群的多個(gè)節(jié)點(diǎn)中。
HDFS中存在一個(gè)名字節(jié)點(diǎn)NameNode和多個(gè)數(shù)據(jù)節(jié)點(diǎn)DataNode
NameNode:存儲(chǔ)元數(shù)據(jù)信息、元數(shù)據(jù)保存在內(nèi)存/磁盤(pán)中、保存文件、block、datanode之間的映射關(guān)系
DataNode:存儲(chǔ)block內(nèi)容、存儲(chǔ)在磁盤(pán)中、維護(hù)了block id到文件的映射關(guān)系
2.HDFS優(yōu)點(diǎn)
支持超大文件:
支持超大文件。超大文件在這里指的是幾百M(fèi),幾百GB,甚至幾TB大小的文件。一般來(lái)說(shuō)hadoop的文件系統(tǒng)會(huì)存儲(chǔ)TB級(jí)別或者PB級(jí)別的數(shù)據(jù)。所以在企業(yè)的應(yīng)用中,數(shù)據(jù)節(jié)點(diǎn)有可能有上千個(gè)。
檢測(cè)和快速應(yīng)對(duì)硬件故障:
在集群的環(huán)境中,硬件故障是常見(jiàn)的問(wèn)題。因?yàn)橛猩锨_(tái)服務(wù)器連接在一起,這樣會(huì)導(dǎo)致高故障率。因此故障檢測(cè)和自動(dòng)恢復(fù)是hdfs文件系統(tǒng)的一個(gè)設(shè)計(jì)目標(biāo)。
流式數(shù)據(jù)訪問(wèn):
Hdfs的數(shù)據(jù)處理規(guī)模比較大,應(yīng)用一次需要訪問(wèn)大量的數(shù)據(jù),同時(shí)這些應(yīng)用一般都是批量處理,而不是用戶(hù)交互式處理。應(yīng)用程序能以流的形式訪問(wèn)數(shù)據(jù)集。主要的是數(shù)據(jù)的吞吐量,而不是訪問(wèn)速度。
簡(jiǎn)化的一致性模型:
大部分hdfs操作文件時(shí),需要一次寫(xiě)入,多次讀取。在hdfs中,一個(gè)文件一旦經(jīng)過(guò)創(chuàng)建、寫(xiě)入、關(guān)閉后,一般就不需要修改了。這樣簡(jiǎn)單的一致性模型,有利于提高吞吐量。
高容錯(cuò)性:
數(shù)據(jù)自動(dòng)保存多個(gè)副本,副本丟失后自動(dòng)恢復(fù)
可構(gòu)建在廉價(jià)機(jī)器上:
構(gòu)建在廉價(jià)機(jī)器上可以輕松的通過(guò)擴(kuò)展機(jī)器數(shù)量來(lái)近乎線性的提高集群存儲(chǔ)能力
3.HDFS缺點(diǎn)
低延遲數(shù)據(jù)訪問(wèn):
低延遲數(shù)據(jù)。如和用戶(hù)進(jìn)行交互的應(yīng)用,需要數(shù)據(jù)在毫秒或秒的范圍內(nèi)得到響應(yīng)。由于hadoop針對(duì)高數(shù)據(jù)吞吐量做了優(yōu)化,犧牲了獲取數(shù)據(jù)的延遲,所以對(duì)于低延遲來(lái)說(shuō),不適合用hadoop來(lái)做。
大量的小文件:
Hdfs支持超大的文件,是通過(guò)數(shù)據(jù)分布在數(shù)據(jù)節(jié)點(diǎn),數(shù)據(jù)的元數(shù)據(jù)保存在名字節(jié)點(diǎn)上。名字節(jié)點(diǎn)的內(nèi)存大小,決定了hdfs文件系統(tǒng)可保存的文件數(shù)量。雖然現(xiàn)在的系統(tǒng)內(nèi)存都比較大,但大量的小文件還是會(huì)影響名字節(jié)點(diǎn)的性能。
多用戶(hù)寫(xiě)入文件、修改文件:
Hdfs的文件只能有一次寫(xiě)入,不支持修改和追加寫(xiě)入(2.0版本支持追加),也不支持修改。只有這樣數(shù)據(jù)的吞吐量才能大。
三、HDFS技術(shù)細(xì)節(jié)
1.Block
最基本的存儲(chǔ)單位。
在HDFS中,有一個(gè)特別重要的概念:數(shù)據(jù)塊(Block)。前面介紹到,在HDFS中存儲(chǔ)的文件都是超大數(shù)據(jù)的文件,我們可以把這個(gè)超大規(guī)模的文件以一個(gè)標(biāo)準(zhǔn)切分成幾塊,分別存儲(chǔ)到不同的磁盤(pán)上。這個(gè)標(biāo)準(zhǔn)就稱(chēng)為Block。Block 默認(rèn)的大小為64(128)M。這樣做有以下幾點(diǎn)好處:
1.文件塊可以保存在不同的磁盤(pán)上。在HDFS系統(tǒng)中,一個(gè)文件可以分成不同的Block存儲(chǔ)在不同的磁盤(pán)上。
2.簡(jiǎn)化存儲(chǔ)系統(tǒng)。這樣不需要管理文件,而是管理文件塊就可以了。
3.有利于數(shù)據(jù)的復(fù)制。在HDFS系統(tǒng)中,一個(gè)block一般會(huì)復(fù)制3份
4.對(duì)于文件內(nèi)容而言,一個(gè)文件的長(zhǎng)度大小是size,那么從文件的0偏移開(kāi)始,按照固定的大小,順序?qū)ξ募M(jìn)行劃分并編號(hào),劃分好的每一個(gè)塊稱(chēng)一個(gè)Block。HDFS默認(rèn)Block大小是128MB,以一個(gè)256MB文件,共有256/128=2個(gè)Block.
5.不同于普通文件系統(tǒng)的是,HDFS中,如果一個(gè)文件小于一個(gè)數(shù)據(jù)塊的大小,并不占用整個(gè)數(shù)據(jù)塊存儲(chǔ)空間
2.NameNode
NameNode維護(hù)著HDFS中的元信息,包括文件和Block之間關(guān)系的信息、Block數(shù)量信息、Block和DataNode之間的關(guān)系信息,數(shù)據(jù)格式參照如下:
FileName replicas block-Ids id2host
例如: /test/a.log,3,{b1,b2},[{b1:[h0,h1,h3]},{b2:[h0,h2,h4]}]
NameNode中的元數(shù)據(jù)信息存儲(chǔ)在內(nèi)存/文件中,內(nèi)存中為實(shí)時(shí)信息,文件中為數(shù)據(jù)鏡像作為持久化存儲(chǔ)使用。
文件包括:
fsimage 元數(shù)據(jù)鏡像文件。存儲(chǔ)某NameNode元數(shù)據(jù)信息,并不是實(shí)時(shí)同步內(nèi)存中的數(shù)據(jù)。
edits 操作日志文件
fstime 保存最近一次checkpoit的時(shí)間
當(dāng)有寫(xiě)請(qǐng)求時(shí),NameNode會(huì)首先寫(xiě)editlog到磁盤(pán)edits文件中,成功后才會(huì)修改內(nèi)存,并向客戶(hù)端返回
所以,fsimage中的數(shù)據(jù)并不是實(shí)時(shí)的數(shù)據(jù),而是在達(dá)到條件時(shí)再進(jìn)行更新,更新過(guò)程需要SNN參與
NameNode的metadata信息會(huì)在啟動(dòng)后加載到內(nèi)存中
3.SecondaryNameNode
SecondaryNameNode并不是NameNode的熱備份,而是協(xié)助者幫助NameNode進(jìn)行元數(shù)據(jù)的合并,從另外的角度來(lái)看可以提供一定的備份功能,但并不是熱備,這種合并過(guò)程可能會(huì)造成極端情況下數(shù)據(jù)丟失!可以從ssn中恢復(fù)部分?jǐn)?shù)據(jù),但是無(wú)法恢復(fù)全部。
何時(shí)出發(fā)數(shù)據(jù)合并?:
根據(jù)配置文件設(shè)置的時(shí)間間隔:fs.checkpoint.period 默認(rèn)3600秒
根據(jù)配置文件設(shè)置的edits log大小 fs.checkpoint.size 默認(rèn)64MB
合并過(guò)程:

達(dá)到條件后 snn會(huì)將nn中的fsimage和edits文件拷貝過(guò)來(lái),同時(shí)nn中會(huì)創(chuàng)建一個(gè)新的edits.new文件,新的讀寫(xiě)請(qǐng)求會(huì)寫(xiě)入到這個(gè)edits.new中,在snn中將拷貝過(guò)來(lái)的fsimage和edits合并為一個(gè)新的fsimage,最后snn將合并完成的fsimage文件拷貝回nn中替換之前的fsimage,nn再將edtis.new改為edits
由于NameNode實(shí)時(shí)數(shù)據(jù)都在內(nèi)存中,此處的合并指的是磁盤(pán)中的持久化的數(shù)據(jù)的處理。
snn并不是nn的熱備,但是能保存大部分備份數(shù)據(jù)。原因就在于edits.new中的數(shù)據(jù)丟失了就找不回來(lái)了
通常NameNode和SNN要放置到不同機(jī)器中以此提升性能,并提供一定的元數(shù)據(jù)安全性。
ps:hadoop2.0有了HA熱備機(jī)制之后,1.0中的secondarynamenode,checkpointnode,buckcupnode這些都不需要了
4.DataNode
在hadoop中,數(shù)據(jù)是存放在DataNode上面的。是以Block的形式存儲(chǔ)的。
DataNode節(jié)點(diǎn)會(huì)不斷向NameNode節(jié)點(diǎn)發(fā)送心跳報(bào)告。
初始化時(shí),每個(gè)數(shù)據(jù)節(jié)點(diǎn)將當(dāng)前存儲(chǔ)的數(shù)據(jù)塊告知NameNode節(jié)點(diǎn)。
通過(guò)向NameNode主動(dòng)發(fā)送心跳保持與其聯(lián)系(3秒一次)
后續(xù)DataNode節(jié)點(diǎn)在工作的過(guò)程中,數(shù)據(jù)節(jié)點(diǎn)仍會(huì)不斷的更新NameNode節(jié)點(diǎn)與之對(duì)應(yīng)的元數(shù)據(jù)信息,并接受來(lái)自NameNode節(jié)點(diǎn)的指令,創(chuàng)建、移動(dòng)或者刪除本地磁盤(pán)上的數(shù)據(jù)塊。
如果10分鐘都沒(méi)收到dn的心跳,則認(rèn)為其已經(jīng)lost,并copy其上的block到其他dn
Replication。多復(fù)本。默認(rèn)是三個(gè)。
5.Block副本放置策略:
第一個(gè)副本:放置在上傳文件的DN,如果是集群外提交,就隨機(jī)選擇一臺(tái)磁盤(pán)不太滿(mǎn),cpu不太忙的節(jié)點(diǎn)
第二個(gè)副本:放置在第一個(gè)副本不同機(jī)架的節(jié)點(diǎn)上
第三個(gè)副本:放置在與第一個(gè)副本相同機(jī)架的節(jié)點(diǎn)上(機(jī)架內(nèi)通訊比機(jī)架間通訊塊)
更多副本:隨機(jī)節(jié)點(diǎn)
**機(jī)架感知策略(參看文章)
四、HDFS的shell操作
常用命令:
hadoop fs -mkdir /user/trunk
hadoop fs -ls /user
hadoop fs -lsr /user? (遞歸的)
hadoop fs -put test.txt /user/trunk
hadoop fs -put test.txt .? (復(fù)制到hdfs當(dāng)前目錄下,首先要?jiǎng)?chuàng)建當(dāng)前目錄)
hadoop fs -get /user/trunk/test.txt . (復(fù)制到本地當(dāng)前目錄下)
hadoop fs -cat /user/trunk/test.txt
hadoop fs -tail /user/trunk/test.txt? (查看最后1000字節(jié))
hadoop fs -rm /user/trunk/test.txt
hadoop fs -rmdir /user/trunk
hadoop fs -help ls (查看ls命令的幫助文檔)
五、HDFS執(zhí)行流程
1.HDFS讀流程

使用HDFS提供的客戶(hù)端開(kāi)發(fā)庫(kù)Client,向遠(yuǎn)程的Namenode發(fā)起RPC請(qǐng)求;
Namenode會(huì)視情況返回文件的部分或者全部block列表,對(duì)于每個(gè)block,Namenode都會(huì)返回有該block拷貝的DataNode地址;
客戶(hù)端開(kāi)發(fā)庫(kù)Client會(huì)選取離客戶(hù)端最接近的DataNode來(lái)讀取block;如果客戶(hù)端本身就是DataNode,那么將從本地直接獲取數(shù)據(jù).
讀取完當(dāng)前block的數(shù)據(jù)后,關(guān)閉與當(dāng)前的DataNode連接,并為讀取下一個(gè)block尋找最佳的DataNode;
當(dāng)讀完列表的block后,且文件讀取還沒(méi)有結(jié)束,客戶(hù)端開(kāi)發(fā)庫(kù)會(huì)繼續(xù)向Namenode獲取下一批的block列表。
讀取完一個(gè)block都會(huì)進(jìn)行checksum驗(yàn)證,如果讀取datanode時(shí)出現(xiàn)錯(cuò)誤,客戶(hù)端會(huì)通知Namenode,然后再?gòu)南乱粋€(gè)擁有該block拷貝的datanode繼續(xù)讀。
當(dāng)文件最后一個(gè)塊也都讀取完成后,datanode會(huì)連接namenode告知關(guān)閉文件。
2.HDFS的寫(xiě)流程

使用HDFS提供的客戶(hù)端開(kāi)發(fā)庫(kù)Client,向遠(yuǎn)程的Namenode發(fā)起RPC請(qǐng)求;
Namenode會(huì)檢查要?jiǎng)?chuàng)建的文件是否已經(jīng)存在,創(chuàng)建者是否有權(quán)限進(jìn)行操作,成功則會(huì)為文件創(chuàng)建一個(gè)記錄,否則會(huì)讓客戶(hù)端拋出異常;
當(dāng)客戶(hù)端開(kāi)始寫(xiě)入文件的時(shí)候,開(kāi)發(fā)庫(kù)會(huì)將文件切分成多個(gè)packets,并在內(nèi)部以數(shù)據(jù)隊(duì)列"data queue"的形式管理這些packets,并向Namenode申請(qǐng)新的blocks。,獲取用來(lái)存儲(chǔ)replicas的合適的datanodes列表, 列表的大小根據(jù)在Namenode中對(duì)replication的設(shè)置而定
開(kāi)始以pipeline(管道)的形式將packet寫(xiě)入所 有的replicas中。開(kāi)發(fā)庫(kù)把packet以流的方式寫(xiě)入第一個(gè)datanode,該datanode把該packet存儲(chǔ)之后,再將其傳遞給在此 pipeline中的下一個(gè)datanode,直到最后一個(gè)datanode,這種寫(xiě)數(shù)據(jù)的方式呈流水線的形式。
最后一個(gè)datanode成功存儲(chǔ)之后會(huì)返回一個(gè)ack packet,在pipeline里傳遞至客戶(hù)端,在客戶(hù)端的開(kāi)發(fā)庫(kù)內(nèi)部維護(hù)著"ack queue",成功收到datanode返回的ack packet后會(huì)從"ack queue"移除相應(yīng)的packet。
在讀取的時(shí)候,如果client與datanode通信時(shí)遇到一個(gè)錯(cuò)誤,那么它就會(huì)去嘗試對(duì)這個(gè)塊來(lái)說(shuō)下一個(gè)最近的塊。它也會(huì)記住那個(gè)故障節(jié)點(diǎn)的datanode,以保證不會(huì)再對(duì)之后的塊進(jìn)行徒勞無(wú)益的嘗試。client也會(huì)確認(rèn)datanode發(fā)來(lái)的數(shù)據(jù)的校驗(yàn)和。如果發(fā)現(xiàn)一個(gè)損壞的塊,它就會(huì)在client試圖從別的datanode中讀取一個(gè)塊的副本之前報(bào)告給namenode。
這個(gè)設(shè)計(jì)的一個(gè)重點(diǎn)是,client直接聯(lián)系datanode去檢索數(shù)據(jù),并被namenode指引到塊中最好的datanode。因?yàn)閿?shù)據(jù)流在此集群中是在所有datanode分散進(jìn)行的。所以這種設(shè)計(jì)能使HDFS可擴(kuò)展到最大的并發(fā)client數(shù)量。同時(shí),namenode只不過(guò)提供塊的位置請(qǐng)求(存儲(chǔ)在內(nèi)存中,十分高效),不是提供數(shù)據(jù)。否則如果客戶(hù)端數(shù)量增長(zhǎng),namenode就會(huì)快速成為一個(gè)“瓶頸”。
3.HDFS的刪除流程
先在NameNode上執(zhí)行節(jié)點(diǎn)名字的刪除。
當(dāng)NameNode執(zhí)行delete方法時(shí),它只標(biāo)記操作涉及的需要被刪除的數(shù)據(jù)塊,而不會(huì)主動(dòng)聯(lián)系這些數(shù)據(jù)塊所在的DataNode節(jié)點(diǎn)。
當(dāng)保存著這些數(shù)據(jù)塊的DataNode節(jié)點(diǎn)向NameNode節(jié)點(diǎn)發(fā)送心跳時(shí),在心跳應(yīng)答里,NameNode節(jié)點(diǎn)會(huì)向DataNode發(fā)出指令,從而把數(shù)據(jù)刪除掉。
所以在執(zhí)行完delete方法后的一段時(shí)間內(nèi),數(shù)據(jù)塊才能被真正的刪除掉。
**安全模式
在重新啟動(dòng)HDFS后,會(huì)立即進(jìn)入安全模式,此時(shí)不能操作hdfs中的文件,只能查看目錄文件名等,讀寫(xiě)操作都不能進(jìn)行。
namenode啟動(dòng)時(shí),需要載入fsimage文件到內(nèi)存,同時(shí)執(zhí)行edits文件中各項(xiàng)操作
一旦在內(nèi)存中成功建立文件系統(tǒng)元數(shù)據(jù)的映射,則創(chuàng)建一個(gè)新的fsimage文件(這個(gè)步驟不需要SNN的參與)和一個(gè)空的編輯文件。
此時(shí)namenode文件系統(tǒng)對(duì)于客戶(hù)端來(lái)說(shuō)是只讀的。
再此階段NameNode收集各個(gè)DataNode的報(bào)告,當(dāng)數(shù)據(jù)塊達(dá)到最小復(fù)本數(shù)以上時(shí),會(huì)被認(rèn)為是“安全”的,在一定比例的數(shù)據(jù)塊被確定為安全后,再經(jīng)過(guò)若干時(shí)間,安全模式結(jié)束
當(dāng)檢測(cè)到副本數(shù)不足的數(shù)據(jù)塊時(shí),該塊會(huì)被復(fù)制直到到達(dá)最小副本數(shù),系統(tǒng)中數(shù)據(jù)塊的位置并不是namenode維護(hù)的,而是以塊列表的形式存儲(chǔ)在datanode中。
當(dāng)啟動(dòng)報(bào)如下錯(cuò)誤時(shí):
org.apache.hadoop.dfs.SafeModeException: Cannot delete /user/hadoop/input. Name node is in safe mode
使用如下命令退出安全模式:
hadoop dfsadmin -safemode leave
六、 HDFS FileSystem JavaAPI
待補(bǔ)充