hdfs有很多特點:
① 儲存多個副本,且提供容錯機制,副本丢失或當機自動恢複。預設存3份。
② 運作在廉價的機器上。
③ 适合大資料的處理。多大?多小?hdfs預設會将檔案分割成block,64m為1個block,不足一64m的就以實際檔案大小為block存在datanode中。然後将block按鍵值對(形如:block1: host2,host1,host3)存儲在hdfs上,并将鍵值對的映射存到namenode的記憶體中。一個鍵值對的映射大約為150個位元組(如果存儲1億個檔案,則namenode需要20g空間),如果小檔案太多,則會在namenode中産生相應多的鍵值對映射,那namenode記憶體的負擔會很重。而且處理大量小檔案速度遠遠小于處理同等大小的大檔案的速度。每一個小檔案要占用一個slot,而task啟動将耗費大量時間甚至大部分時間都耗費在啟動task和釋放task上。
如上圖所示,hdfs也是按照master和slave的結構。分namenode、secondarynamenode、datanode這幾個角色。
namenode:是master節點,是hdfs的管理者。管理資料塊映射;處理用戶端的讀寫請求;負責維護元資訊;配置副本政策;管理hdfs的名稱空間等
secondarynamenode:負責元資訊和日志的合并;合并fsimage和fsedits然後再發給namenode。
ps:namenode和secondarynamenode兩者沒有關系,更加不是備份,namenode挂掉的時候secondarynamenode并不能頂替他的工作。
然而,由于namenode單點問題,在hadoop2中namenode以叢集的方式部署主要表現為hdfs feration和ha,進而省去了secondarynode的存在,關于hadoop2.x的改進移步hadoop1.x 與hadoop2.x 架構變化分析
datanode:slave節點,奴隸,幹活的。負責存儲client發來的資料塊block;執行資料塊的讀寫操作。
熱備份:b是a的熱備份,如果a壞掉。那麼b馬上運作代替a的工作。
冷備份:b是a的冷備份,如果a壞掉。那麼b不能馬上代替a工作。但是b上存儲a的一些資訊,減少a壞掉之後的損失。
fsimage:中繼資料鏡像檔案(檔案系統的目錄樹。)是在namenode啟動時對整個檔案系統的快照
edits:啟動後namenode對中繼資料的記錄檔(針對檔案系統做的修改操作記錄)
namenode記憶體中存儲的是=fsimage+edits。
隻有在namenode重新開機時,edit logs才會合并到fsimage檔案中,進而得到一個檔案系統的最新快照。但是在産品叢集中namenode是很少重新開機的,這也意味着當namenode運作了很長時間後,edit logs檔案會變得很大。在這種情況下就會出現下面一些問題:
edit logs檔案會變的很大,怎麼去管理這個檔案是一個挑戰。
namenode的重新開機會花費很長時間,因為有很多在edit logs中的改動要合并到fsimage檔案上。
如果namenode挂掉了,那我們就丢失了很多改動因為此時的fsimage檔案非常舊。[筆者認為在這個情況下丢失的改動不會很多, 因為丢失的改動應該是還在記憶體中但是沒有寫到edit logs的這部分。]
那麼其實可以在namenode中起一個程式定時進行新的fsimage=edits+fsimage的更新,但是有一個更好的方法是secondarynamenode。
secondarynamenode的職責是合并namenode的edit logs到fsimage檔案中,減少namenode下一次重新開機過程
上面的圖檔展示了secondary namenode是怎麼工作的。
首先,它定時到namenode去擷取edit logs,并更新到自己的fsimage上。
一旦它有了新的fsimage檔案,它将其拷貝回namenode中。
namenode在下次重新開機時會使用這個新的fsimage檔案,進而減少重新開機的時間。
secondary namenode的整個目的是在hdfs中提供一個檢查點。它隻是namenode的一個助手節點。這也是它在社群内被認為是檢查點節點的原因。secondarynamenode負責定時預設1小時,從namenode上,擷取fsimage和edits來進行合并,然後再發送給namenode。減少namenode的工作量和下一次重新開機過程。
工作原理
寫操作:
有一個檔案filea,100m大小。client将filea寫入到hdfs上。
hdfs按預設配置。
hdfs分布在三個機架上rack1,rack2,rack3。
a. client将filea按64m分塊。分成兩塊,block1和block2;
b. client向namenode發送寫資料請求,如圖藍色虛線①------>。
c. namenode節點,記錄block資訊(即鍵值對的映射)。并傳回可用的datanode,如粉色虛線②------>。
block1: host2,host1,host3
block2: host7,host8,host4
原理:
namenode具有rackaware機架感覺功能,這個可以配置。
若client為datanode節點,那存儲block時,規則為:副本1,同client的節點上;副本2,不同機架節點上;副本3,同第二個副本機架的另一個節點上;其他副本随機挑選。
若client不為datanode節點,那存儲block時,規則為:副本1,随機選擇一個節點上;副本2,不同副本1,機架上;副本3,同副本2相同的另一個節點上;其他副本随機挑選。
d. client向datanode發送block1;發送過程是以流式寫入。
流式寫入過程,
1>将64m的block1按64k的package劃分;
2>然後将第一個package發送給host2;
3>host2接收完後,将第一個package發送給host1,同時client想host2發送第二個package;
4>host1接收完第一個package後,發送給host3,同時接收host2發來的第二個package。
5>以此類推,如圖紅線實線所示,直到将block1發送完畢。
6>host2,host1,host3向namenode,host2向client發送通知,說“消息發送完了”。如圖粉紅顔色實線所示。
7>client收到host2發來的消息後,向namenode發送消息,說我寫完了。這樣就真完成了。如圖黃色粗實線
8>發送完block1後,再向host7,host8,host4發送block2,如圖藍色實線所示。
9>發送完block2後,host7,host8,host4向namenode,host7向client發送通知,如圖淺綠色實線所示。
10>client向namenode發送消息,說我寫完了,如圖黃色粗實線。。。這樣就完畢了。
分析,通過寫過程,我們可以了解到:
①寫1t檔案,我們需要3t的存儲,3t的網絡流量帶寬。
②在執行讀或寫的過程中,namenode和datanode通過heartbeat進行儲存通信,确定datanode活着。如果發現datanode死掉了,就将死掉的datanode上的資料,放到其他節點去。讀取時,要讀其他節點去。
③挂掉一個節點,沒關系,還有其他節點可以備份;甚至,挂掉某一個機架,也沒關系;其他機架上,也有備份。
讀操作:
讀操作就簡單一些了,如圖所示,client要從datanode上,讀取filea。而filea由block1和block2組成。
那麼,讀操作流程為:
a. client向namenode發送讀請求。
b. namenode檢視metadata資訊(鍵值對的映射),傳回filea的block的位置。
block1:host2,host1,host3
block2:host7,host8,host4
c. block的位置是有先後順序的,先讀block1,再讀block2。而且block1去host2上讀取;然後block2,去host7上讀取;
上面例子中,client位于機架外,那麼如果client位于機架内某個datanode上,例如,client是host6。那麼讀取的時候,遵循的規律是:
優先讀取本機架上的資料。
hdfs中常用到的指令
1、hadoop fs
hadoop fs -ls /
hadoop fs -lsr
hadoop fs -mkdir /user/hadoop
hadoop fs -put a.txt /user/hadoop/
hadoop fs -get /user/hadoop/a.txt /
hadoop fs -cp src dst
hadoop fs -mv src dst
hadoop fs -cat /user/hadoop/a.txt
hadoop fs -rm /user/hadoop/a.txt
hadoop fs -rmr /user/hadoop/a.txt
hadoop fs -text /user/hadoop/a.txt
hadoop fs -copyfromlocal localsrc dst 與hadoop fs -put功能類似。
hadoop fs -movefromlocal localsrc dst 将本地檔案上傳到hdfs,同時删除本地檔案。
2、hadoop fsadmin?
hadoop dfsadmin -report
hadoop dfsadmin -safemode enter | leave | get | wait
hadoop dfsadmin -setbalancerbandwidth 1000
3、hadoop fsck
4、start-balancer.sh
注意,看了hdfs的布局,以及作用,這裡需要考慮幾個問題:
1、既然namenode,存儲小檔案不太合适,那小檔案如何處理?
至少有兩種場景下會産生大量的小檔案:
(1)這些小檔案都是一個大邏輯檔案的一部分。由于hdfs在2.x版本開始支援對檔案的append,是以在此之前儲存無邊界檔案(例如,log檔案)(譯者注:持續産生的檔案,例如日志每天都會生成)一種常用的方式就是将這些資料以塊的形式寫入hdfs中(a very common pattern for saving unbounded files (e.g. log files) is to write them in chunks into hdfs)。
(2)檔案本身就是很小。設想一下,我們有一個很大的圖檔語料庫,每一個圖檔都是一個獨一的檔案,并且沒有一種很好的方法來将這些檔案合并為一個大的檔案。
(1)第一種情況
對于第一種情況,檔案是許多記錄(records)組成的,那麼可以通過調用hdfs的sync()方法(和append方法結合使用),每隔一定時間生成一個大檔案。或者,可以通過寫一個程式來來合并這些小檔案(可以看一下nathan marz關于consolidator一種小工具的文章)。
(2)第二種情況
對于第二種情況,就需要某種形式的容器通過某種方式來對這些檔案進行分組。hadoop提供了一些選擇:
har file
hadoop archives (har files)是在0.18.0版本中引入到hdfs中的,它的出現就是為了緩解大量小檔案消耗namenode記憶體的問題。har檔案是通過在hdfs上建構一個分層檔案系統來工作。har檔案通過hadoop archive指令來建立,而這個指令實 際上是運作了一個mapreduce作業來将小檔案打包成少量的hdfs檔案(譯者注:将小檔案進行合并幾個大檔案)。對于client端來說,使用har檔案沒有任何的改變:所有的原始檔案都可見以及可通路(隻是使用har://url,而不是hdfs://url),但是在hdfs中中檔案數卻減少了。
讀取har中的檔案不如讀取hdfs中的檔案更有效,并且實際上可能較慢,因為每個har檔案通路需要讀取兩個索引檔案以及還要讀取資料檔案本身(如下圖)。盡管har檔案可以用作mapreduce的輸入,但是沒有特殊的魔法允許mapreduce直接操作har在hdfs塊上的所有檔案(although har files can be used as input to mapreduce, there is no special magic that allows maps to operate over all the files in the har co-resident on a hdfs block)。 可以考慮通過建立一種input format,充分利用har檔案的局部性優勢,但是目前還沒有這種input format。需要注意的是:multifileinputsplit,即使在hadoop-4565的改進,但始終還是需要每個小檔案的尋找。我們非常有興趣看到這個與sequencefile進行對比。 在目前看來,hars可能最好僅用于存儲文檔(at the current time hars are probably best used purely for archival purposes.)
2、namenode在記憶體中存儲了meta等資訊,那麼記憶體的瓶頸如何解決?
3、secondary是namenode的冷備份,那麼secondarynamenode和namenode不應該放到一台裝置上,因為namenode宕掉之後,secondarynamenode一般也就死了,那講secondarynamenode放到其他機器上,如何配置?
4、namenode當機後,如何利用secondarynamenode上面的備份的資料,恢複namenode?
5、裝置當機,那麼,檔案的replication備份數目,就會小于配置值,那麼該怎麼辦?
本文作者:佚名
來源:51cto