一.Datanode與NameNode區(qū)別
大數(shù)據(jù)中,HDFS集群以Master-Slave模式運(yùn)行缭贡,主要有兩類節(jié)點(diǎn):一個(gè)Namenode(即Master)和多個(gè)Datanode(即Slave)炮姨。Namenode管理文件系統(tǒng)的Namespace纫骑。它維護(hù)著文件系統(tǒng)樹(filesystem tree)以及文件樹中所有的文件和文件夾的元數(shù)據(jù)(metadata)衙熔。
Namenode 管理者文件系統(tǒng)的Namespace(名稱空間)嫉你。它維護(hù)著文件系統(tǒng)樹(filesystem tree)以及文件樹中所有的文件和文件夾的元數(shù)據(jù)(metadata)月帝。管理這些信息的文件有兩個(gè)躏惋,分別是Namespace 鏡像文件(Namespace image)和操作日志文件(edit log)幽污,這些信息被Cache在RAM中,當(dāng)然簿姨,這兩個(gè)文件也會(huì)被持久化存儲(chǔ)在本地硬盤距误。Namenode記錄著每個(gè)文件中各個(gè)塊所在的數(shù)據(jù)節(jié)點(diǎn)的位置信息,但是他并不持久化存儲(chǔ)這些信息扁位,因?yàn)檫@些信息會(huì)在系統(tǒng)啟動(dòng)時(shí)從數(shù)據(jù)節(jié)點(diǎn)重建准潭。
Datanode是文件系統(tǒng)的工作節(jié)點(diǎn),他們根據(jù)客戶端或者是namenode的調(diào)度存儲(chǔ)和檢索數(shù)據(jù)域仇,并且定期向namenode發(fā)送他們所存儲(chǔ)的塊(block)的列表刑然。
Namenode負(fù)責(zé)文件元數(shù)據(jù)的操作,DataNode負(fù)責(zé)處理文件內(nèi)容的讀寫請求暇务,跟文件內(nèi)容相關(guān)的數(shù)據(jù)流不會(huì)經(jīng)過Namenode泼掠,只會(huì)詢問它跟那個(gè)DataNode聯(lián)系,否則Namenode會(huì)成為系統(tǒng)的瓶頸垦细。
副本存放在哪些DataNode上由Namenode來控制择镇,根據(jù)全局情況作出塊放置決定,讀取文件時(shí)Namenode盡量讓用戶先讀取最近的副本括改,降低帶塊消耗和讀取延時(shí)腻豌。
Namenode全權(quán)管理數(shù)據(jù)塊的復(fù)制,它周期性地從集群中的每個(gè)Datanode接收心跳信號和塊狀態(tài)報(bào)告。接收到心跳信號意味著該Datanode節(jié)點(diǎn)工作正常吝梅。塊狀態(tài)報(bào)告包含了一個(gè)該Datanode上所有數(shù)據(jù)塊的列表虱疏。
Namenode是主節(jié)點(diǎn),存儲(chǔ)文件的元數(shù)據(jù)如文件名苏携,文件目錄結(jié)構(gòu)订框,文件屬性(生成時(shí)間,副本數(shù)兜叨,文件權(quán)限)以及每個(gè)文件的塊列表穿扳,以及塊所在的DataNode等等。
二.MapReduce框架
1.WordCount代碼解析
Map方法:
public void map(Object key, Text value, Context context) throws IOException, InterruptedException {…}
這里有三個(gè)參數(shù)国旷,前面兩個(gè)Object key, Text value就是輸入的key和value矛物,第三個(gè)參數(shù)Context context這是可以記錄輸入的key和value,例如:context.write(word, one);此外context還會(huì)記錄map運(yùn)算的狀態(tài)跪但。
Reduce方法:
public void reduce(Text key, Iterable values, Context context) throws IOException, InterruptedException {…}
reduce函數(shù)的輸入也是一個(gè)key/value的形式履羞,不過它的value是一個(gè)迭代器的形式Iterable values,也就是說reduce的輸入是一個(gè)key對應(yīng)一組的值的value屡久,reduce也有context和map的context作用一致
Job job=new Job(conf,"word count");
job.setJarByClass(WordCount.class);
job.setMapperClass(TokenizerMapper.class);
job.setCombinerClass(IntSumReducer.class);
job.setReducerClass(IntSumReducer.class);
第一行就是在構(gòu)建一個(gè)job忆首,在mapreduce框架里一個(gè)mapreduce任務(wù)也叫mapreduce作業(yè)也叫做一個(gè)mapreduce的job,而具體的map和reduce運(yùn)算就是task了被环,這里我們構(gòu)建一個(gè)job糙及,構(gòu)建時(shí)候有兩個(gè)參數(shù),一個(gè)是conf這個(gè)就不累述了筛欢,一個(gè)是這個(gè)job的名稱浸锨。
第二行就是裝載程序員編寫好的計(jì)算程序,例如我們的程序類名就是WordCount了版姑。這里我要做下糾正柱搜,雖然我們編寫mapreduce程序只需要實(shí)現(xiàn)map函數(shù)和reduce函數(shù),但是實(shí)際開發(fā)我們要實(shí)現(xiàn)三個(gè)類剥险,第三個(gè)類是為了配置mapreduce如何運(yùn)行map和reduce函數(shù)聪蘸,準(zhǔn)確的說就是構(gòu)建一個(gè)mapreduce能執(zhí)行的job了,例如WordCount類表制。
第三行和第五行就是裝載map函數(shù)和reduce函數(shù)實(shí)現(xiàn)類了健爬,這里多了個(gè)第四行,這個(gè)是裝載Combiner類夫凸,這個(gè)我后面講mapreduce運(yùn)行機(jī)制時(shí)候會(huì)講述浑劳,其實(shí)本例去掉第四行也沒有關(guān)系,但是使用了第四行理論上運(yùn)行效率會(huì)更好夭拌。
FileInputFormat.addInputPath(job, new Path(otherArgs[0]));
FileOutputFormat.setOutputPath(job, new Path(otherArgs[1]));
System.exit(job.waitForCompletion(true) ? 0 : 1);
第一行就是構(gòu)建輸入的數(shù)據(jù)文件魔熏,第二行是構(gòu)建輸出的數(shù)據(jù)文件衷咽,最后一行如果job運(yùn)行成功了,我們的程序就會(huì)正常退出蒜绽。
2. MapReduce運(yùn)行機(jī)制
首先是客戶端要編寫好mapreduce程序镶骗,配置好mapreduce的作業(yè)也就是job,接下來就是提交job了躲雅,提交job是提交到JobTracker上的鼎姊,這個(gè)時(shí)候JobTracker就會(huì)構(gòu)建這個(gè)job,具體就是分配一個(gè)新的job任務(wù)的ID值相赁,接下來它會(huì)做檢查操作相寇,這個(gè)檢查就是確定輸出目錄是否存在,如果存在那么job就不能正常運(yùn)行下去钮科,JobTracker會(huì)拋出錯(cuò)誤給客戶端唤衫,接下來還要檢查輸入目錄是否存在,如果不存在同樣拋出錯(cuò)誤绵脯,如果存在JobTracker會(huì)根據(jù)輸入計(jì)算輸入分片(Input Split)佳励,如果分片計(jì)算不出來也會(huì)拋出錯(cuò)誤,至于輸入分片我后面會(huì)做講解的蛆挫,這些都做好了JobTracker就會(huì)配置Job需要的資源了赃承。分配好資源后,JobTracker就會(huì)初始化作業(yè)悴侵,初始化主要做的是將Job放入一個(gè)內(nèi)部的隊(duì)列瞧剖,讓配置好的作業(yè)調(diào)度器能調(diào)度到這個(gè)作業(yè),作業(yè)調(diào)度器會(huì)初始化這個(gè)job畜挨,初始化就是創(chuàng)建一個(gè)正在運(yùn)行的job對象(封裝任務(wù)和記錄信息)筒繁,以便JobTracker跟蹤job的狀態(tài)和進(jìn)程噩凹。
初始化完畢后巴元,作業(yè)調(diào)度器會(huì)獲取輸入分片信息(input split),每個(gè)分片創(chuàng)建一個(gè)map任務(wù)驮宴。接下來就是任務(wù)分配了逮刨,這個(gè)時(shí)候tasktracker會(huì)運(yùn)行一個(gè)簡單的循環(huán)機(jī)制定期發(fā)送心跳給jobtracker,心跳間隔是5秒堵泽,程序員可以配置這個(gè)時(shí)間修己,心跳就是jobtracker和tasktracker溝通的橋梁,通過心跳迎罗,jobtracker可以監(jiān)控tasktracker是否存活睬愤,也可以獲取tasktracker處理的狀態(tài)和問題,同時(shí)tasktracker也可以通過心跳里的返回值獲取jobtracker給它的操作指令纹安。任務(wù)分配好后就是執(zhí)行任務(wù)了尤辱。在任務(wù)執(zhí)行時(shí)候jobtracker可以通過心跳機(jī)制監(jiān)控tasktracker的狀態(tài)和進(jìn)度砂豌,同時(shí)也能計(jì)算出整個(gè)job的狀態(tài)和進(jìn)度,而tasktracker也可以本地監(jiān)控自己的狀態(tài)和進(jìn)度光督。當(dāng)jobtracker獲得了最后一個(gè)完成指定任務(wù)的tasktracker操作成功的通知時(shí)候阳距,jobtracker會(huì)把整個(gè)job狀態(tài)置為成功,然后當(dāng)客戶端查詢job運(yùn)行狀態(tài)時(shí)候(注意:這個(gè)是異步操作)结借,客戶端會(huì)查到j(luò)ob完成的通知的筐摘。如果job中途失敗,mapreduce也會(huì)有相應(yīng)機(jī)制處理船老,一般而言如果不是程序員程序本身有bug咖熟,mapreduce錯(cuò)誤處理機(jī)制都能保證提交的job能正常完成。
1. 輸入分片(input split):在進(jìn)行map計(jì)算之前柳畔,mapreduce會(huì)根據(jù)輸入文件計(jì)算輸入分片(input split)球恤,每個(gè)輸入分片(input split)針對一個(gè)map任務(wù),輸入分片(input split)存儲(chǔ)的并非數(shù)據(jù)本身荸镊,而是一個(gè)分片長度和一個(gè)記錄數(shù)據(jù)的位置的數(shù)組咽斧,輸入分片(input split)往往和hdfs的block(塊)關(guān)系很密切,假如我們設(shè)定hdfs的塊的大小是64mb躬存,如果我們輸入有三個(gè)文件张惹,大小分別是3mb、65mb和127mb岭洲,那么mapreduce會(huì)把3mb文件分為一個(gè)輸入分片(input split)宛逗,65mb則是兩個(gè)輸入分片(input split)而127mb也是兩個(gè)輸入分片(input split),換句話說我們?nèi)绻趍ap計(jì)算前做輸入分片調(diào)整盾剩,例如合并小文件雷激,那么就會(huì)有5個(gè)map任務(wù)將執(zhí)行,而且每個(gè)map執(zhí)行的數(shù)據(jù)大小不均告私,這個(gè)也是mapreduce優(yōu)化計(jì)算的一個(gè)關(guān)鍵點(diǎn)屎暇。