HDFS原理解析(整體架構,讀寫操作流程及源代碼查看等)


前言

HDFS 是一個能夠面向大規模數據使用的。可進行擴展的文件存儲與傳遞系統。是一種同意文件通過網絡在多台主機上分享的文件系統,可讓多機器上的多用戶分享文件和存儲空間。讓實際上是通過網絡來訪問文件的動作。由程序與用戶看來,就像是訪問本地的磁盤一般。即使系統中有某些節點脫機,總體來說系統仍然能夠持續運作而不會有數據損失。

一、HDFS體系結構

1、Namenode
Namenode是整個文件系統的管理節點。它維護着整個文件系統的文件文件夾樹,文件/文件夾的元信息和每個文件相應的數據塊列表, 接收用戶的操作請求。
文件包含:
①fsimage:元數據鏡像文件。存儲某一時段NameNode內存元數據信息。
②edits:操作日志文件。
③fstime:保存近期一次checkpoint的時間
以上這些文件是保存在linux的文件系統中。通過hdfs-site.xml的dfs.namenode.name.dir屬性進行設置。

查看NameNode的fsimage與edits內容
這個兩個文件里的內容使用普通文本編輯器是無法直接查看的,幸運的是hadoop為此准備了專門的工具用於查看文件的內容,這些工具分別為oev和oiv,能夠使用hdfs調用運行。

啟動server:bin/hdfs oiv -i 某個fsimage文件

bash$ bin/hdfs oiv -i fsimage
14/04/07 13:25:14 INFO offlineImageViewer.WebImageViewer: WebImageViewer started.
Listening on /127.0.0.1:5978. Press Ctrl+C to stop the viewer.

查看內容:bin/hdfs dfs -ls -R webhdfs://127.0.0.1:5978/

bash$ bin/hdfs dfs -ls webhdfs://127.0.0.1:5978/
Found 2 items
drwxrwx–* - root supergroup 0 2014-03-26 20:16 webhdfs://127.0.0.1:5978/tmp
drwxr-xr-x - root supergroup 0 2014-03-31 14:08 webhdfs://127.0.0.1:5978/user

導出fsimage的內容:bin/hdfs oiv -p XML -i
tmp/dfs/name/current/fsimage_0000000000000000055 -o fsimage.xml

bash$ bin/hdfs oiv -p XML -i fsimage -o fsimage.xml
0000055 -o fsimage.xml

查看edtis的內容:bin/hdfs oev -i
tmp/dfs/name/current/edits_0000000000000000057-0000000000000000186 -o edits.xml

bash$ bin/hdfs oev -i
tmp/dfs/name/current/edits_0000000000000000057-0000000000000000186 -o edits.xml

2、Datanode
提供真實文件數據的存儲服務。


文件塊( block): 最主要的存儲單位。
對於文件內容而言,一個文件的長度大小是size。那么從文件的0偏移開始,依照固定的大小,順序對文件進行划分並編號,划分好的每個塊稱一個Block。

HDFS默認Block大小是128MB。 因此。一個256MB文件。共同擁有256/128=2個Block.
與普通文件系統不同的是,在 HDFS中,假設一個文件小於一個數據塊的大小,並不占用整個數據塊存儲空間。
Replication:多復本。默認是三個。通過hdfs-site.xml的dfs.replication屬性進行設置。

二、數據存儲操作

1、數據存儲: block
默認數據塊大小為128MB,可配置。若文件大小不到128MB,則單獨存成一個block。
為何數據塊如此之大?
傳輸數據時間超過尋道時間(高吞吐率)
一個文件存儲方式?
按大小被切分成若干個block。存儲到不同節點上。默認情況下每個block有三個副本。

HDFS Block的設計理念:一個文件由哪些塊組成。

一個塊存儲在哪些節點上。優點:易於分攤到各個節點。

例如以下:

block1:node1,node2,node3
block2:node2,node3,node4
block3:node4,mode5,node6
block4:node5,node6.node7

2、數據存儲: staging
HDFS client上傳數據到HDFS時,首先,在本地緩存數據,當數據達到一個block大小時。請求NameNode分配一個block。 NameNode會把block所在的DataNode的地址告訴HDFS client。 HDFS client會直接和DataNode通信,把數據寫到DataNode節點一個block文件里。

3、數據存儲:讀文件操作

1.首先調用FileSystem對象的open方法,事實上是一個DistributedFileSystem的實例。

2.DistributedFileSystem通過rpc獲得文件的第一批block的locations,同一個block依照反復數會返回多個locations,這些locations依照hadoop拓撲結構排序,距離client近的排在前面。

3.前兩步會返回一個FSDataInputStream對象,該對象會被封裝DFSInputStream對象,DFSInputStream能夠方便的管理datanode和namenode數據流。client調用read方法。DFSInputStream最會找出離client近期的datanode並連接。

4.數據從datanode源源不斷的流向client。

5.假設第一塊的數據讀完了,就會關閉指向第一塊的datanode連接。接着讀取下一塊。

這些操作對client來說是透明的,client的角度看來僅僅是讀一個持續不斷的流。

6.假設第一批block都讀完了, DFSInputStream就會去namenode拿下一批block的locations。然后繼續讀。假設全部的塊都讀完,這時就會關閉掉全部的流。
假設在讀數據的時候, DFSInputStream和datanode的通訊發生異常。就會嘗試正在讀的block的排序第二近的datanode,而且會記錄哪個datanode錯誤發生,剩余的blocks讀的時候就會直接跳過該datanode。 DFSInputStream也會檢查block數據校驗和,假設發現一個壞的block,就會先報告到namenode節點,然后DFSInputStream在其它的datanode上讀該block的鏡像。

該設計就是client直接連接datanode來檢索數據而且namenode來負責為每個block提供最優的datanode。 namenode僅僅處理block location的請求,這些信息都載入在namenode的內存中。hdfs通過datanode集群能夠承受大量client的並發訪問。
Hadoop2.6.0源代碼查看讀過程

4、數據存儲:寫文件操作

1.client通過調用DistributedFileSystem的create方法創建新文件。

2.DistributedFileSystem通過RPC調用namenode去創建一個沒有blocks關聯的新文件,創建前, namenode會做各種校驗。比方文件是否存在,client有無權限去創建等。假設校驗通過。 namenode就會記錄下新文件,否則就會拋出IO異常。

3.前兩步結束后。會返回FSDataOutputStream的對象,與讀文件的時候類似, FSDataOutputStream被封裝成DFSOutputStream。DFSOutputStream能夠協調namenode和datanode。client開始寫數據到DFSOutputStream,DFSOutputStream會把數據切成一個個小的packet。然后排成隊列data quene。

4.DataStreamer會去處理接受data quene,它先詢問namenode這個新的block最適合存儲的在哪幾個datanode里(比方反復數是3。那么就找到3個最適合的datanode),把他們排成一個pipeline。DataStreamer把packet按隊列輸出到管道的第一個datanode中。第一個datanode又把packet輸出到第二個datanode中。以此類推。

5.DFSOutputStream另一個對列叫ack quene。也是由packet組成,等待datanode的收到響應,當pipeline中的全部datanode都表示已經收到的時候,這時akc quene才會把相應的packet包移除掉。


假設在寫的過程中某個datanode錯誤發生,會採取下面幾步:
1) pipeline被關閉掉;
2)為了防止防止丟包ack quene里的packet會同步到data quene里;
3)把產生錯誤的datanode上當前在寫但未完畢的block刪掉;
4)block剩下的部分被寫到剩下的兩個正常的datanode中。
5)namenode找到另外的datanode去創建這個塊的復制。當然。這些操作對client來說是無感知的。

6.client完畢寫數據后調用close方法關閉寫入流。

7.DataStreamer把剩余得包都刷到pipeline里,然后等待ack信息,收到最后一個ack后,通知datanode把文件標視為已完畢。

注意:client運行write操作后,寫完的block才是可見的,正在寫的block對client是不可見的,僅僅有調用sync方法。client才確保該文件的寫操作已經全部完畢。當client調用close方法時,會默認調用sync方法。

是否須要手動調用取決你依據程序須要在數據健壯性和吞吐率之間的權衡。

Hadoop2.6.0源代碼查看寫過程


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM