一、hadoop概念
Hadoop由兩部分組成,一是負(fù)責(zé)存儲(chǔ)與管理文件的分布式文件系統(tǒng)HDFS、二是負(fù)責(zé)處理與計(jì)算的MapReduce的計(jì)算框架。
二、HDFS
1.namenode
負(fù)責(zé)管理工作(管理文件系統(tǒng)的目錄結(jié)構(gòu),元數(shù)據(jù)信息,響應(yīng)用戶請(qǐng)求)
包含了兩個(gè)核心的數(shù)據(jù)結(jié)構(gòu),F(xiàn)sImage和EditLog。
FsImage:用于維護(hù)整個(gè)文件系統(tǒng)數(shù)以及文件樹中所有的文件和文件夾的元數(shù)據(jù)
EditLog:記錄了所有針對(duì)文件的創(chuàng)建,刪除,重命名等操作
2.Seconday NameNode
為主namenode內(nèi)存中的文件系統(tǒng)元數(shù)據(jù),創(chuàng)建檢查點(diǎn),在文件系統(tǒng)中設(shè)置一個(gè)檢查點(diǎn)來幫助NameNode更好的工作,不是取代掉NameNode,也不是備份SecondayName有兩個(gè)作用
一是鏡像備份,二是日志與鏡像的定期合并。兩個(gè)同時(shí)進(jìn)行稱為checkpoint。
鏡像備份的作用:備份fsImage
合并作用:防止如果NameNode節(jié)點(diǎn)故障,namenode下次啟動(dòng)時(shí),會(huì)把fsImage加載到內(nèi)存中,應(yīng)用editLog,EditLog往往很大,可以減少重啟時(shí)間,同時(shí)保證HDFS系統(tǒng)的完整性。
3.dataname
以塊的形式進(jìn)行存儲(chǔ)數(shù)據(jù)
在HDFS中,我們真實(shí)的數(shù)據(jù)是由DataNode來負(fù)責(zé)來存儲(chǔ)的,但是數(shù)據(jù)具體被存儲(chǔ)到了哪個(gè)DataNode節(jié)點(diǎn)等元數(shù)據(jù)信息則是由我們的NameNode來存儲(chǔ)的。

三、mapreduce
- mapreduce概念
*將復(fù)雜運(yùn)行與大規(guī)模集群上的并行運(yùn)算的過程高度抽象到兩個(gè)函數(shù):map和reduce
*采用"分而治之"策略,一個(gè)存儲(chǔ)在分布式文件系統(tǒng)中的大規(guī)模數(shù)據(jù)集,會(huì)被切分成許多獨(dú)立分片,這些可以被多個(gè)map任務(wù)執(zhí)行。
map(映射):將小數(shù)據(jù)集解析成一批<key,value>
reduce(遞歸):將所有相同Key的value合并起來
2.mapreduced的結(jié)構(gòu)體系
主從式的結(jié)構(gòu),JobTrack只有一個(gè),TaskTracker有很多個(gè)
image.png
JobTracker的職責(zé)
1.負(fù)責(zé)接受用戶提交給的任務(wù)
2.將計(jì)算任務(wù)分配給TaskTracker
3.跟蹤監(jiān)控TaskTracker的任務(wù)和task的執(zhí)行狀況
TaskTracker的職責(zé)
執(zhí)行JobTracker分配給的計(jì)算任務(wù)task。
3.mapreduce的 input split

hdfs以固定大小的block為基本單位存儲(chǔ)數(shù)據(jù),而對(duì)于MR而言,集中處理單位split,輸入分片(input split)存儲(chǔ)的并非數(shù)據(jù)本身,而是一個(gè)分片長度和一個(gè)記錄數(shù)據(jù)的位置的數(shù)組。大多數(shù)情況下,理想的分片大小是一個(gè)hdfs塊。
4.shuffle過程



1.map端shuffle

①寫入環(huán)形內(nèi)存緩沖區(qū)
因?yàn)轭l繁的磁盤I/O操作會(huì)嚴(yán)重的降低效率,因此“中間結(jié)果”不會(huì)立馬寫入磁盤,而是優(yōu)先存儲(chǔ)到map節(jié)點(diǎn)的“環(huán)形內(nèi)存緩沖區(qū)”,并做一些預(yù)排序以提高效率,當(dāng)寫入的數(shù)據(jù)量達(dá)到預(yù)先設(shè)置的闕值后便會(huì)執(zhí)行一次I/O操作將數(shù)據(jù)寫入到磁盤。每個(gè)map任務(wù)都會(huì)分配一個(gè)環(huán)形內(nèi)存緩沖區(qū),用于存儲(chǔ)map任務(wù)輸出的鍵值對(duì)(默認(rèn)大小100MB,mapreduce.task.io.sort.mb調(diào)整)以及對(duì)應(yīng)的partition,被緩沖的(key,value)對(duì)已經(jīng)被序列化(為了寫入磁盤)。
②緩存達(dá)到閾值,溢寫到磁盤文件 溢寫前會(huì)進(jìn)行分區(qū),分區(qū)內(nèi)排序和合并(可選)
2.1分區(qū)partition
在將map()函數(shù)后得到的(key,value)對(duì)寫入到緩沖區(qū)之間,需要進(jìn)行分區(qū),這樣能把map任務(wù)處理結(jié)果發(fā)送給指定的reducer去執(zhí)行,從而達(dá)到負(fù)載均衡,避免數(shù)據(jù)傾斜MapReduce提供默認(rèn)的分區(qū)類(HashPartitioner)
public class HashPartitioner<K, V> extends Partitioner<K, V> {
/** Use {@link Object#hashCode()} to partition. */
public int getPartition(K key, V value,
int numReduceTasks) {
return (key.hashCode() & Integer.MAX_VALUE) % numReduceTasks;
}
}
getPartition()方法有三個(gè)參數(shù),前兩個(gè)指的是mapper任務(wù)輸出的鍵值對(duì),而第三個(gè)參數(shù)指的是設(shè)置的reduce任務(wù)的數(shù)量,默認(rèn)值為1。因?yàn)槿魏握麛?shù)與1相除的余數(shù)肯定是0。也就是說默認(rèn)的getPartition()方法的返回值總是0,也就是Mapper任務(wù)的輸出默認(rèn)總是送給同一個(gè)Reducer任務(wù),最終只能輸出到一個(gè)文件中。如果想要讓mapper輸出的結(jié)果給多個(gè)reducer處理,那么只需要寫一個(gè)類,讓其繼承Partitioner類,并重寫getPartition()方法,讓其針對(duì)不同情況返回不同數(shù)值即可。并在最后通過job設(shè)置指定分區(qū)類和reducer任務(wù)數(shù)量即可。
2.2分區(qū)內(nèi)排序
旦緩沖區(qū)內(nèi)容達(dá)到閾值(mapreduce.map.io.sort.spill.percent,默認(rèn)0.80,或者80%),就會(huì)會(huì)鎖定這80%的內(nèi)存,并在每個(gè)分區(qū)中對(duì)其中的鍵值對(duì)按鍵進(jìn)行sort排序,具體是將數(shù)據(jù)按照partition和key兩個(gè)關(guān)鍵字進(jìn)行排序,排序結(jié)果為緩沖區(qū)內(nèi)的數(shù)據(jù)按照partition為單位聚集在一起,同一個(gè)partition內(nèi)的數(shù)據(jù)按照key有序。排序完成后會(huì)創(chuàng)建一個(gè)溢出寫文件(臨時(shí)文件),然后開啟一個(gè)后臺(tái)線程把這部分?jǐn)?shù)據(jù)以一個(gè)臨時(shí)文件的方式溢出寫(spill)到本地磁盤中
2.3合并(可選)
如果客戶端自定義了Combiner(相當(dāng)于map階段的reduce),則會(huì)在分區(qū)排序后到溢寫出前自動(dòng)調(diào)用combiner,將相同的key的value相加,這樣的好處就是減少溢寫到磁盤的數(shù)據(jù)量。這個(gè)過程叫“合并”
④歸并merge
當(dāng)一個(gè)map task處理的數(shù)據(jù)很大,以至于超過緩沖區(qū)內(nèi)存時(shí),就會(huì)生成多個(gè)spill文件。此時(shí)就需要對(duì)同一個(gè)map任務(wù)產(chǎn)生的多個(gè)spill文件進(jìn)行歸并生成最終的一個(gè)已分區(qū)且已排序的大文件。配置屬性mapreduce.task.io.sort.factor控制著一次最多能合并多少流,默認(rèn)值是10。這個(gè)過程包括排序和合并(可選),歸并得到的文件內(nèi)鍵值對(duì)有可能擁有相同的key,這個(gè)過程如果client設(shè)置過Combiner,也會(huì)合并相同的key值的鍵值對(duì)(根據(jù)上面提到的combine的調(diào)用時(shí)機(jī)可知)。
溢出寫文件歸并完畢后,Map將刪除所有的臨時(shí)溢出寫文件,并告知NodeManager任務(wù)已完成,只要其中一個(gè)MapTask完成,ReduceTask就開始復(fù)制它的輸出(Copy階段分區(qū)輸出文件通過http的方式提供給reducer)
map shuffle一些特點(diǎn)
1.每個(gè)Map任務(wù)分配一個(gè)緩存
2.MapReduce默認(rèn)100MB緩存
3.設(shè)置溢寫比例0.8
4.分區(qū)默認(rèn)采用哈希函數(shù)
5.排序是默認(rèn)的操作
6.排序后可以合并(Combine)
7.合并不能改變最終結(jié)果
8.在Map任務(wù)全部結(jié)束之前進(jìn)行歸并
9.歸并得到一個(gè)大的文件,放在本地磁盤
10.文件歸并時(shí),如果溢寫文件數(shù)量大于預(yù)定值(默認(rèn)是3)則可以再次啟動(dòng)Combiner,少于3不需要
合并(Combine)和歸并(Merge)的區(qū)別:
兩個(gè)鍵值對(duì)<“a”,1>和<“a”,1>,如果合并,會(huì)得到<“a”,2>,如果歸并,會(huì)得到<“a”,<1,1>>
3.Reduce端的Shuffle過程

①領(lǐng)取數(shù)據(jù)
Map端的shuffle過程結(jié)束后,結(jié)果會(huì)保存在本地磁盤中,Reduce任務(wù)只需要把這些數(shù)據(jù)領(lǐng)?。‵etch)回來首先存放到緩存當(dāng)中
②歸并數(shù)據(jù)
如果緩存到一定閾值,就會(huì)像發(fā)生溢寫操作,當(dāng)溢寫程序啟動(dòng)時(shí),具有相同key的鍵值對(duì)會(huì)被歸并,如果用戶定義了combiner,則歸并后還可以執(zhí)行combiner,減少寫入磁盤的數(shù)據(jù)量,每個(gè)溢寫過程結(jié)束后,都會(huì)在磁盤生成一個(gè)溢寫文件,當(dāng)溢寫文件過多時(shí)也會(huì)像Map一樣被歸并成一個(gè)大文件,歸并是也會(huì)進(jìn)行排序,當(dāng)數(shù)據(jù)很少時(shí),寫入緩存就行,不需要溢寫到磁盤,而是直接在內(nèi)存中執(zhí)行歸并操作,直接輸出給Reduce任務(wù)
面試寶典之mapreduce的shuffle過程
首先shuffle是貫徹整個(gè)mapreduce過程,可以分為2部分,map端的shuffle和reduce端的shuffle。map端shuffle,map任務(wù)執(zhí)行后的中間結(jié)果”不會(huì)立馬寫入磁盤,而是優(yōu)先存儲(chǔ)到map節(jié)點(diǎn)的“環(huán)形內(nèi)存緩沖區(qū)”(默認(rèn)100MB),當(dāng)內(nèi)存緩存區(qū)達(dá)到一定閾值(默認(rèn)0.8)就會(huì)進(jìn)行溢寫到磁盤文件,溢寫之前會(huì)先進(jìn)行分區(qū),然后分區(qū)內(nèi)的排序,如果客戶端自定義了Combiner,還會(huì)進(jìn)行合并操作。最后如果有多個(gè)溢寫文件。會(huì)對(duì)這個(gè)多個(gè)溢寫文件進(jìn)行歸并生成最終的一個(gè)已分區(qū)且已排序的大文件。reduce端shuffle先領(lǐng)取不同節(jié)點(diǎn)map任務(wù)執(zhí)行結(jié)束數(shù)據(jù)存儲(chǔ)到緩存區(qū),當(dāng)緩存區(qū)到達(dá)一定閾值,就是發(fā)生溢寫操作,溢寫之前具有相同key的鍵值對(duì)會(huì)被歸并,如果客戶端定義combiner,歸并后還可以執(zhí)行combiner(合并),但溢寫文件過多,也會(huì)歸并成一個(gè)大文件。輸出給Reduce任務(wù),整個(gè)shuffle才最終結(jié)束。
四、hadoop 2.0新特性
1.針對(duì)1.0中NameNode的單點(diǎn)故障問題,在2.0中引入了新的HA機(jī)制:即如果Active的NameNode節(jié)點(diǎn)掛掉,處于Standby的NameNode節(jié)點(diǎn)將替換掉它繼續(xù)工作
2.引入yarn資源管理

Yarn是Hadoop2.0中的資源管理系統(tǒng),它的基本設(shè)計(jì)思想是將MR1.0中的JobTracker拆分成兩個(gè)獨(dú)立的服務(wù):一個(gè)是全局的資源管理器ResouceManager和每個(gè)應(yīng)用程序特有的AppMaster。
在Yarn平臺(tái)中,各個(gè)組件的詳細(xì)功能如下:
1.ResouceManager
是一個(gè)全局的資源管理器,負(fù)責(zé)整個(gè)系統(tǒng)的資源管理和分配,ResouceManager相當(dāng)于Hadoop1.0中的JobTracker的部分職能:資源分配。
2.AppMaster
負(fù)責(zé)管理單個(gè)應(yīng)用程序,即負(fù)責(zé)一個(gè)Job生命周期內(nèi)的所有工作,監(jiān)控整個(gè)任務(wù)的執(zhí)行,跟蹤整個(gè)任務(wù)的狀態(tài),處理任務(wù)失敗以異常情況。AppMaster類似老的框架中的JobTracker的部分職能:任務(wù)分配與任務(wù)監(jiān)控。特別注意:每一個(gè)Job(而不是每一種)都有一個(gè)相應(yīng)的APPMaster,APPMaster可以運(yùn)行在除主節(jié)點(diǎn)ResouceManager節(jié)點(diǎn)以外的其它機(jī)器上,但是在Hadoop1.0中,JobTracker的位置是固定的。
3.NodeManager
NodeManager 是 YARN 集群當(dāng)中真正資源的提供者,是真正執(zhí)行應(yīng)用程序的容器的提供者, 監(jiān)控應(yīng)用程序的資源使用情況(CPU,內(nèi)存,硬盤,網(wǎng)絡(luò)),并通過心跳向集群資源調(diào)度器 ResourceManager 進(jìn)行匯報(bào)以更新自己的健康狀態(tài)。同時(shí)其也會(huì)監(jiān)督 Container 的生命周期 管理,監(jiān)控每個(gè) Container 的資源使用(內(nèi)存、CPU 等)情況,追蹤節(jié)點(diǎn)健康狀況,管理日志和不同應(yīng)用程序用到的附屬服務(wù)(auxiliary service)。
YARN 作業(yè)執(zhí)行流程

1>首先,用戶的應(yīng)用程序通過Yarn平臺(tái)的客戶端程序?qū)⑽覀兊膽?yīng)用程序提交給我們的YARN平臺(tái)
2>YARN平臺(tái)的ResouceManager接受到我們客戶端提交給的應(yīng)用程序后,將應(yīng)用程序交給某個(gè)NodeManager,并在其上面啟動(dòng)一個(gè)新的進(jìn)程AppMaster
3>AppMaster首先為應(yīng)用程序在ResouceManager中進(jìn)行注冊(cè),這樣用戶可以通過ResouceManager查看應(yīng)用程序的執(zhí)行進(jìn)度
4>注冊(cè)完之后,APPMaster將通過Rpc協(xié)議向ResouceManager申請(qǐng)資源并領(lǐng)取相應(yīng)的資源
5>獲取到資源后,APPMaster便于對(duì)應(yīng)的NodeManager節(jié)點(diǎn)進(jìn)行通信,要求其啟動(dòng)相應(yīng)的任務(wù)
6>各個(gè)任務(wù)在執(zhí)行的過程中將通過RPC協(xié)議向APPMaster匯報(bào)自己的執(zhí)行進(jìn)度和執(zhí)行狀況,以便讓APPMaster可以隨時(shí)掌握各個(gè)任務(wù)的執(zhí)行狀況,進(jìn)而在任務(wù)運(yùn)行失敗時(shí)可以重新啟動(dòng)相應(yīng)的任務(wù)。
7>mapper任務(wù)和reducer任務(wù)執(zhí)行完之后,AppMaster向ResouceManager節(jié)點(diǎn)注銷并關(guān)閉自己,此時(shí)資源得到回收,應(yīng)用程序執(zhí)行完畢。
