一、hdfs上傳和下載文件流程
- hdfs上傳
客戶端向namenode發(fā)出請求建立通信獲得存儲文件塊的datanode節(jié)點(diǎn),然后客戶端將文件按照塊的大小進(jìn)行分塊(hadoop2.7.3開始由64MB變成128MB),客戶端按照順序?qū)lock逐個(gè)傳到響應(yīng)的datanode上,并由接收Black的datanode負(fù)責(zé)向其它的datanode復(fù)制block的副本

詳解
1.客戶端向namenode請求上傳文件,namenode檢查目標(biāo)文件,父目錄是否存在
2.namenode返回可使用資源,客戶端根據(jù)使用資源對要寫入的數(shù)據(jù)進(jìn)行分塊
3.客戶端請求第一個(gè)Block上傳位置
4.namenode返回3個(gè)datanode節(jié)點(diǎn),分別是data1,data2,data3
5.客戶端請求向第一個(gè)data1上傳block,data1收到請求會調(diào)用data2,然后data2會調(diào)用data3,將通道建立完成,逐級響應(yīng)客戶端
6.客戶端開始向data1上傳第一個(gè)block(先從磁盤讀取數(shù)據(jù)放到一個(gè)本地內(nèi)存緩沖),單位為packet(一個(gè)packet為64kb),在寫入data1的時(shí)候會進(jìn)行數(shù)據(jù)校驗(yàn),它并不是通過一個(gè)packet進(jìn)行一次校驗(yàn)而是以chunk為單位進(jìn)行校驗(yàn)(512byte),data1收到packet就會傳給data2,data2傳給data3,第一臺每傳一個(gè)packet會放入一個(gè)應(yīng)答隊(duì)列等待應(yīng)答
7.當(dāng)一個(gè)block傳輸完成之后,datanode進(jìn)行報(bào)告給namenode存儲的塊信息,同時(shí)也告訴客戶端寫入成功
8.客戶端再次請求namenode上傳第二個(gè)block的服務(wù)器(重復(fù)執(zhí)行3-7步)
2.hdfs下載文件
客戶端向hdfs讀數(shù)據(jù),首先要和namenode建立通信來獲得需要讀取文件的元信息(主要是Block的存放文件位置信息),客戶端根據(jù)獲取的信息找到相應(yīng)datanode,逐個(gè)獲取文件的block并在客戶端本地進(jìn)行數(shù)據(jù)追加,從而獲得整個(gè)文件
hdfs下載文件
讀取步驟詳解:
1.client和namenode進(jìn)行通信查詢元數(shù)據(jù)(block所在的datanode節(jié)點(diǎn)),找到block所在的datanode服務(wù)器
2.挑選一臺datanode,請求建立連接(就近原則,然后隨機(jī)),請求建立socket流
3.datanode開始發(fā)送數(shù)據(jù)(從磁盤里面讀取數(shù)據(jù)放入流,以packet為單位來做校驗(yàn))
4.客戶達(dá)以packet為單位接受,首先在本地緩沖,然后寫入目標(biāo)文件,后面的block追加合并到這個(gè)文件,最后合成最終需要的文件
二、mapreduce的shuffle過程
首先shuffle是貫徹整個(gè)mapreduce過程,可以分為2部分,map端的shuffle和reduce端的shuffle。map端shuffle,map任務(wù)執(zhí)行后的中間結(jié)果”不會立馬寫入磁盤,而是優(yōu)先存儲到map節(jié)點(diǎn)的“環(huán)形內(nèi)存緩沖區(qū)”(默認(rèn)100MB),當(dāng)內(nèi)存緩存區(qū)達(dá)到一定閾值(默認(rèn)0.8)就會進(jìn)行溢寫到磁盤文件,溢寫之前會先進(jìn)行分區(qū),然后分區(qū)內(nèi)的排序,如果客戶端自定義了Combiner,還會進(jìn)行合并操作。最后如果有多個(gè)溢寫文件。會對這個(gè)多個(gè)溢寫文件進(jìn)行歸并生成最終的一個(gè)已分區(qū)且已排序的大文件。reduce端shuffle先領(lǐng)取不同節(jié)點(diǎn)map任務(wù)執(zhí)行結(jié)束數(shù)據(jù)存儲到緩存區(qū),當(dāng)緩存區(qū)到達(dá)一定閾值,就是發(fā)生溢寫操作,溢寫之前具有相同key的鍵值對會被歸并,如果客戶端定義combiner,歸并后還可以執(zhí)行combiner(合并),但溢寫文件過多,也會歸并成一個(gè)大文件。輸出給Reduce任務(wù),整個(gè)shuffle才最終結(jié)束。
三、hadoop1.0跟hadoop2.0區(qū)別
- 針對1.0中NameNode的單點(diǎn)故障問題,在2.0中引入了新的HA機(jī)制
2.解決jobTracker等弊端,使用yarn資源管理系統(tǒng)
四、hadoop 數(shù)據(jù)傾斜
就是大量的相同key被partition分配到一個(gè)分區(qū)里,map /reduce程序執(zhí)行時(shí),reduce節(jié)點(diǎn)大部分執(zhí)行完畢,但是有一個(gè)或者幾個(gè)reduce節(jié)點(diǎn)運(yùn)行很慢,導(dǎo)致整個(gè)程序的處理時(shí)間很長,這是因?yàn)槟骋粋€(gè)key的條數(shù)比其他key多很多(有時(shí)是百倍或者千倍之多),這條key所在的reduce節(jié)點(diǎn)所處理的數(shù)據(jù)量比其他節(jié)點(diǎn)就大很多,從而導(dǎo)致某幾個(gè)節(jié)點(diǎn)遲遲運(yùn)行不完。
解決方案:
1.增加jvm內(nèi)存,這適用于第一種情況(唯一值非常少,極少數(shù)值有非常多的記錄值(唯一值少于幾千)),這種情況下,往往只能通過硬件的手段來進(jìn)行調(diào)優(yōu),增加jvm內(nèi)存可以顯著的提高運(yùn)行效率。
2.增加reduce的個(gè)數(shù),這適用于第二種情況(唯一值比較多,這個(gè)字段的某些值有遠(yuǎn)遠(yuǎn)多于其他值的記錄數(shù),但是它的占比也小于百分之一或千分之一),我們知道,這種情況下,
最容易造成的結(jié)果就是大量相同key被partition到一個(gè)分區(qū),從而一個(gè)reduce執(zhí)行了大量的工作,而如果我們增加了reduce的個(gè)數(shù),這種情況相對來說會減輕很多,畢竟計(jì)算的節(jié)點(diǎn)多了,就算工作量還是不均勻的,那也要小很多。
3.自定義分區(qū),這需要用戶自己繼承partition類,指定分區(qū)策略,這種方式效果比較顯著。
4.重新設(shè)計(jì)key,有一種方案是在map階段時(shí)給key加上一個(gè)隨機(jī)數(shù),有了隨機(jī)數(shù)的key就不會被大量的分配到同一節(jié)點(diǎn)(小幾率),待到reduce后再把隨機(jī)數(shù)去掉即可。
5.使用combinner合并,combinner是在map階段,reduce之前的一個(gè)中間階段,在這個(gè)階段可以選擇性的把大量的相同key數(shù)據(jù)先進(jìn)行一個(gè)合并,可以看做是local reduce,然后再交給reduce來處理,這樣做的好處很多,即減輕了map端向reduce端發(fā)送的數(shù)據(jù)量(減輕了網(wǎng)絡(luò)帶寬),也減輕了map端和reduce端中間的shuffle階段的數(shù)據(jù)拉取數(shù)量(本地化磁盤IO速率),推薦使用這種方法。
五、hdfs不適合存小文件的原因
1.namenode會記錄文件的元數(shù)據(jù),如果小文件過多,會造成namenode消耗太大
2.hdfs的設(shè)計(jì)原理是接近磁盤讀取速度,之所以把block塊設(shè)置很大,是因?yàn)橄胱龅綄さ罆r(shí)間遠(yuǎn)小于文件讀取數(shù)據(jù)塊的時(shí)間,接近磁盤讀取速度。
