·第3個副本:放置在與第2個副本相同機架的節點上。分布式文件管理系統有很多,如DFS和HDFS,而HDFS適用於一次寫入、多次查詢的情況.
DFS介紹
由於一台機器的存儲容量有限,一旦數據量達到足夠的級別,就需要將數據存放在多台機器上,這就是分布式文件系統,又稱之為DFS(Distributed FileSystem)。
DFS是HDFS的基礎,本節將簡單講解一下什么是DFS及DFS的結構,隨后引出Hadoop的核心組件HDFS
分布式文件系統DFS是基於Master/Slave模式,通常一個分布式文件系統提供多個供用戶訪問的服務器,一般都會提供備份和容錯的功能。
分布式文件系統管理的物理資源不一定直接連接在本地節點上,而是通過計算機網絡與節點相連,而非文件系統管理的物理存儲資源一定直接連在本地節點上。
DFS的結構
分布式文件系統在物理結構上是由計算機集群中的多個節點構成的,如圖3.1所示。這些節點分為兩類,一類叫“主節點”(Master Node),也被稱為“名稱節點”(NameNode);另一類叫“從節點”(SlaveNode),也被稱為“數據節點”(DataNode)。
HDFS介紹
前面講到的DFS是統稱的分布式文件系統,在Hadoop中實現的分布式文件系統被稱之為HDFS,接下來將會介紹HDFS的基本概念、執行原理及文件的讀寫流程。
HDFS的概念及體系結構
HDFS是Hadoop自帶的分布式文件系統,即Hadoop Distributed File System。HDFS是一個使用Java語言實現的分布式、可橫向擴展的文件系統。
HDFS包括一個名稱節點(NameNode)和若干個數據節點(DataNode),屬於主/從(Master/Slave)關系的結構模型。其中,名稱節點負責管理文件系統的命名空間及客戶端對文件的訪問,也就是中心服務器。
而集群中的數據節點一般是一個節點運行一個數據節點進程,其中每個數據節點上的數據實際上是保存在本地的Linux文件系統中,並在名稱節點的統一調動下,負責處理文件系統客戶端的讀/寫請求,或刪除、創建和復制數據塊等操作。
HDFS的設計
HDFS的設計主要是為了實現存儲大量數據、成本低廉和容錯率高、數據一致性,以及順序訪問數據這4個目標
1.大數據集
HDFS適合存儲大量文件,總存儲量可以達到PB/EB,單個文件一般在幾百兆。
2.基於廉價硬件,容錯率高
Hadoop並不需要運行在昂貴且高可靠的硬件上,其設計運行在商用廉價硬件的集群上,因此對於龐大的集群來說,節點發生故障的幾率還是非常高的。HDFS遇到上述故障時被設計成能夠繼續運行且可以不讓用戶察覺到明顯的中斷。
3.流式數據訪問(一致性模型)
HDFS的構建思路是這樣的:一次寫入、多次讀取是最高效的訪問模式。數據集通常由數據源生成或從數據源復制而來,接着長時間在此數據集上進行各種分析。每次分析都將涉及該數據集的大部分數據甚至全部數據,因此讀取整個數據集的時間延遲比讀取第一條記錄的時間延遲更重要。
4.順序訪問數據
HDFS適用於處理批量數據,而不適合隨機定位訪問。
HDFS的優點和缺點
1.HDFS的優點·
高容錯性:數據自動保存多個副本,副本丟失后自動恢復。
適合批處理:移動計算而非數據,數據位置暴露給計算機框架。·
適合大數據處理:GB、TB,甚至PB級數據,百萬規模以上的文件數量,10k+節點。
可構建在廉價機器上:通過副本提高可靠性,提供了容錯和恢復機制。
2.HDFS的缺點
·不適合低延時數據訪問:尋址時間長,適合讀取大文件,低延遲與高吞吐率。
·不適合小文件存取:占用NameNode大量內存,尋找時間超過讀取時間。
·並發寫入、文件隨機修改:一個文件只能有一個寫入者,僅支持append(日志),不允許修改文件。
HDFS的執行原理
客戶端傳入文件讀寫請求時,NameNode(HDFS的集群管理節點)首先接受客戶端的讀寫服務請求,並根據它保存的Metadata元數據,包括元數據的鏡像文件(fsimage和操作日志edits信息)和DataNode(數據存儲)通信並進行資源協調,Secondary NameNode進行edits和fsimage的合並,同時DataNode之間進行數據復制。
如果要存儲一個大文件,首先要將文件分割成塊,分別放到不同的節點,每塊文件都有3個副本備份,並且有一個專門記錄文件塊存放情況的元數據文件以備查詢,如圖3.2和圖3.3所示。
HDFS的核心概念
1.數據塊(block)
每個磁盤都有默認的數據塊大小,這是磁盤進行數據讀/寫的最小單位。HDFS也有塊的概念,在HDFS 1.x中默認數據塊大小為64MB,在HDFS 2.x中默認數據塊大小為128MB。與單一磁盤上的文件系統相似,HDFS上的文件也被划分成塊大小的多個分塊(chunk),作為獨立的存儲單元。但與面向單一的文件磁盤系統不同的是,HDFS中小於一個塊大小的文件不會占據整個塊的空間(例如一個1MB的文件存儲在一個128MB的塊中時,文件只會使用1MB的磁盤空間,而不是128MB)。
2.NameNode
NameNode為HDFS集群的管理節點,一個集群通常只有一台活動的NameNode,它存放了HDFS的元數據且一個集群只有一份元數據。NameNode的主要功能是接受客戶端的讀寫服務,NameNode保存的Metadata信息包括文件ownership、文件的permissions,以及文件包括哪些Block、Block保存在哪個DataNode等信息。這些信息在啟動后會加載到內存中。
3.DataNode
DataNode中文件的儲存方式是按大小分成若干個Block,存儲到不同的節點上,Block大小和副本數通過Client端上傳文件時設置,文件上傳成功后副本數可以變更,BlockSize不可變更。默認情況下每個Block都有3個副本。
4.SecondaryNameNode
SecondaryNameNode(簡稱SNN),它的主要工作是幫助NameNode合並edits,減少NameNode啟動時間。SNN執行合並時機如下:·根據配置文件設置的時間間隔fs.checkpoint.period,默認3600秒。·根據配置文件設置edits log大小fs.checkpoint.size,規定edits文件的最大值默認是64MB,如圖3.4所示。
5.元數據
元數據保存在NameNode的內存中,以便快速查詢,主要包括fsimage和edits。
·fsimage:元數據鏡像文件(保存文件系統的目錄樹)。
·edits:元數據操作日志(針對目錄樹的修改操作)被寫入共享存儲系統中,比如NFS、JournalNode,內存中保存一份最新的元數據鏡像(fsimage+edits)。
HDFS讀文件流程
(5)當快到達塊的末端時,DFSInputStream會關閉與該DataNode的連接,然后尋找下一個塊最佳的DataNode。對於存儲在HDFS上的文件,我們可以通過客戶端發送讀文件請求,主要步驟如下:
(1)客戶端通過調用FileSystem對象的open()方法打開要讀取的文件,對於HDFS來說,這個對象是DistributedFileSystem的一個實例。
(2)DistributedFileSystem通過使用遠程過程調用(RPC)來調用NameNode,以確定文件起始塊的位置。
(3)對於每個塊,NameNode返回到存有該塊副本的DataNode地址。此外,這些DataNode根據它們與客戶端的距離來排序。如果該客戶端本身就是一個DataNode,那么該客戶端將會從包含有相應數據塊副本的本地DataNode讀取數據。DistributedFileSystem類返回一個FSDataInputStream對象給客戶端並讀取數據,FSDataInputStream轉而封裝DFSInputStream對象,該對象管理着DataNode和NameNode的I/O。接着,客戶端對這個輸入流調用read()方法。
(4)存儲着文件起始幾個塊的DataNode地址的DFSInputStream,接着會連接距離最近的文件中第一個塊所在的DataNode。通過對數據流的反復調用read()方法,實現將數據從DataNode傳輸到客戶端。
(5)當快到達塊的末端時,DFSInputStream會關閉與該DataNode的連接,然后尋找下一個塊最佳的DataNode。
(6)當客戶端從流中讀取數據時,塊是按照打開的DFSInputStream與DataNode新建連接的順序進行讀取的。它也會根據需要詢問NameNode從而檢索下一批數據塊的DataNode的位置。一旦客戶端完成讀取,就對FSDataInputStream調用close()方法,如圖3.5所示。
HDFS寫文件流程
對於存儲在HDFS上的文件也可以寫入內容,可以通過客戶端發送寫文件的請求,主要步驟如下:
(1)客戶端調用DistributedFileSystem對象的create()方法新建文件。
(2)DistributedFileSystem會對NameNode創建一個RPC調用,在文件系統的命名空間中創建一個新文件,需要注意的是,此刻該文件中還沒有相應的數據塊。
(3)NameNode通過執行不同的檢查來確保這個文件不存在而且客戶端有新建該文件的權限。如果這些檢查都通過了,NameNode就會為創建新文件寫下一條記錄;反之,如果文件創建失敗,則向客戶端拋出一個IOException異常。(4)隨后DistributedFileSystem向客戶端返回一個FSDataOutputStream對象,這樣客戶端就可以寫入數據了。和讀取事件類似,FSDataOutputStream封裝一個DFSOutputStream對象,該對象會負責處理DataNode和NameNode之間的通信。在客戶端寫入數據的時候,DFSOutputStream將它分成一個個的數據包,並且寫入內部隊列,被稱之為“數據隊列”(data queue)。
(5)DataStream處理數據隊列,它的任務是選出適合用來存儲數據副本的一組DataNode,並據此要求NameNode分配新的數據塊。這一組DataNode會構成一條管線,DataStream會將數據包流式傳輸到管線中的第一個DataNode,然后依次存儲並發送給下一個DataNode。
(6)DFSOutPutStream也維護着一個內部數據包隊列來等待DataNode的收到確認回執,稱為“確認隊列”(ask queue)。收到管道中所有DataNode確認信息后,該數據包才會從確認隊列刪除。
(7)客戶端完成數據的寫入后,會對數據流調用close()方法,如圖3.6所示。
Block的副本放置策略
HDFS中的文件作為獨立的存儲單元,被划分為塊(block)大小的多個分塊(chunk),在Hadoop 2.x中默認值為128MB。當HDFS中存儲小於一個塊大小的文件時不會占據整個塊的空間,也就是說,1MB的文件存儲時只占用1MB的空間而不是128MB。HDFS的容錯性也要求數據自動保存多個副本,副本的放置策略如圖3.7所示。
·第1個副本:放置在上傳文件的DN;如果是集群外提交,則隨機挑選一台磁盤不太滿、CPU不太忙的節點。
·第2個副本:放置在與第1個副本不同機架的節點上。
·第3個副本:放置在與第2個副本相同機架的節點上。
·更多副本:隨機節點。