《Hadoop》"呶呶不休"(一)HDFS設計思想和相關概念

一、HDFS簡介

1、簡單介紹

HDFS(Hadoop  Distributed  FileSystem),是Hadoop項目的兩大核心之一,源自於Google於2003年10月發表的GFS論文,是對GFS的開源實現。HDFS在最開始是作爲Apache Nutch搜索引擎項目的基礎架構而開發的。

HDFS在設計之初,就是要運行在通用硬件(commodity hardware)上,即廉價的大型服務器集羣上,因此,在設計上就把硬件故障作爲一種常態來考慮,可以保證在部分硬件發生故障的情況下,仍然能夠保證文件系統的整體可用性和可靠性。

HDFS有一下特點:

HDFS是一個高度容錯性的系統,適合部署在廉價的機器上的分佈式文件系統。
HDFS能提供高吞吐量的數據訪問,非常適合大規模數據集上的應用。
HDFS放寬了一部分POSIX約束,來實現流式讀取文件系統數據的目的。
HDFS也是一個易於擴展的分佈式文件系統

2、HDFS設計目標

a、大規模數據集

HDFS用來處理很大的數據集。HDFS上的文件,大小一般都在GB至TB。因此同時,HDFS應該能提供整體較高的數據傳輸帶寬,能在一個集羣裏擴展到數百個節點。一個單一的HDFS實例應該能支撐千萬計的文件。目前在實際應用中,HDFS已經能用來存儲管理PB級的數據了。

b、硬件錯誤

我們應該知道,硬件組件發生故障是常態,而非異常情況。HDFS可能由成百上千的服務器組成,每一個服務器都是廉價通用的普通硬件,任何一個組件都有可能一直失效,因此錯誤檢測和快速、自動恢復是HDFS的核心架構目標,同時能夠通過自身持續的狀態監控快速檢測冗餘並恢復失效的組件。

c、流式數據訪問

流式數據,特點就是,像流水一樣,不是一次過來而是一點一點“流”過來,而處理流式數據也是一點一點處理。

HDFS的設計要求是:能夠高速率、大批量的處理數據,更多地響應"一次寫入、多次讀取"這樣的任務。在HDFS上一個數據集,會被複制分發到不同的存儲節點中。而各式各樣的分析任務多數情況下,都會涉及數據集中的大部分數據。爲了提高數據的吞吐量,Hadoop放寬了POSIX的約束,使用流式訪問來進行高效的分析工作

d、簡化一致性模型

HDFS應用需要一個“一次寫入多次讀取”的文件訪問模型。一個文件經過創建、寫入和關閉之後就不需要改變了。這一假設簡化了數據一致性問題,並且使高吞吐量的數據訪問成爲可能。MapReduce應用或網絡爬蟲應用都非常適合這個模型。目前還有計劃在將來擴充這個模型,使之支持文件的附加寫操作。

e、移動計算代價比移動數據代價低

一個應用請求的計算,離它操作的數據越近就越高效,這在數據達到海量級別的時候更是如此。將計算移動到數據附近,比之將數據移動到應用所在之處顯然更好,HDFS提供給應用這樣的接口。

f、可移植性

HDFS在設計時就考慮到平臺的可移植性,這種特性方便了HDFS作爲大規模數據應用平臺的推廣。

3、HDFS的優缺點

通過上述的介紹,我們可以發現HDFS的優點是:

a、高容錯性:數據自動保存多個副本,副本丟失後,會自動恢復。
b、適合批處理:移動計算而非數據、數據位置需要暴露給計算框架。
c、適合大數據處理:GB、TB、甚至PB級數據、百萬規模以上的文件數量,1000以上節點規模。
d、流式文件訪問:一次性寫入,多次讀取;保證數據一致性。
e、可構建在廉價機器上:通過多副本提高可靠性,提供了容錯和恢復機制。

而HDFS同樣有自己的缺點:

1)不適合低延遲數據訪問

HDFS的設計目標有一點是:處理大型數據集,高吞吐率。這勢必要以高延遲爲代價的。因此HDFS不適合處理一些用戶要求時間比較短的低延遲應用請求。

2)不適合小文件存取

一是因此存取大量小文件需要消耗大量的尋地時間(比如拷貝大量小文件與拷貝同等大小的一個大文件) 。
二是因爲namenode把元信息存儲在內存中,一個節點的內存是有限的。一個block元信息的內存消耗大約是150 byte。而存儲1億個block和1億個小文件都會消耗掉namenode 20GB內存,哪個適合?當然是1億個block(大文件)更省內存。

3)不適合併發寫入、文件隨機修改

HDFS上的文件只能有一個寫者,也僅僅支持append操作,不支持多用戶對同一文件的寫操作,以及在文件任意位置進行修改。

二、HDFS設計思想

現在想象一下這種情況:有四個文件 0.5TB的file1,1.2TB的file2,50GB的file3,100GB的file4;有7個服務器,每個服務器上有10個1TB的硬盤。

在存儲方式上,我們可以將這四個文件存儲在同一個服務器上(當然大於1TB的文件需要切分),我們需要使用一個文件來記錄這種存儲的映射關係吧。用戶是可以通過這種映射關係來找到節點硬盤相應的文件的。那麼缺點也就暴露了出來:

第一、負載不均衡。因爲文件大小不一致,勢必會導致有的節點磁盤的利用率高,有的節點磁盤利用率低。

第二、網絡瓶頸問題。一個過大的文件存儲在一個節點磁盤上,當有並行處理時,每個線程都需要從這個節點磁盤上讀取這個文件的內容,那麼就會出現網絡瓶頸,不利於分佈式的數據處理。

我們來看看HDFS的設計思想:以下圖爲例,來進行解釋。

HDFS將50G的文件file3切成多個Block(存儲塊),每一個Block的大小都是固定的,比如128MB,它把這多個數據塊以多副本的行式存儲在各個節點上 ,再使用一個文件把哪個塊存儲在哪些節點上的映射關係存儲起來。有了這樣的映射關係,用戶讀取文件的時候就會很容易讀取到。每個節點上都有這樣的Block數據,它會分開網絡瓶頸,利於分佈式計算,解決了上面的第二個問題。因爲每個塊的大小是一樣的,所以很容易實現負載均衡,解決了上面的第一個問題。

三、HDFS相關概念

1、塊(Block)概念

在我們熟知的Windows、Linux等系統上,文件系統會將磁盤空間劃分爲每512字節一組,我們稱之爲"磁盤塊",它是文件系統讀寫操作的最小單位。而文件系統的數據塊(Block)一般是磁盤塊的整數倍,即每次讀寫的數據量必須是磁盤塊的整數倍。

在傳統的文件系統中,爲了提高磁盤的讀寫效率,一般以數據塊爲單位,而不是以字節爲單位,比如機械硬盤包含了磁頭和轉動部件,在讀取數據時有一個尋道的過程,通國轉動盤片和移動磁頭的位置,來找到數據在機械硬盤中的存儲位置,然後才能進行讀寫。在I/O開銷中,機械硬盤的尋址時間時最耗時的部分,一旦找到第一條記錄,剩下的順序讀取效率是非常高的,因此以塊爲單位讀寫數據,可以把磁盤尋道時間分攤到大量數據中。

HDFS同樣引入了塊(Block)的概念,塊是HDFS系統當中的最小存儲單位,在hadoop2.0中默認大小爲128MB。在HDFS上的文件會被拆分成多個塊,每個塊作爲獨立的單元進行存儲。多個塊存放在不同的DataNode上,整個過程中 HDFS系統會保證一個塊存儲在一個數據節點上 。但值得注意的是 如果某文件大小或者文件的最後一個塊沒有到達128M,則不會佔據整個塊空間 。

當然塊大小可以在配置文件中hdfs-default.xml中進行修改(此值可以修改)

<property>
  <name>dfs.blocksize</name>
  <value>134217728</value>
  <description>默認塊大小,以字節爲單位。可以使用以下後綴(不區分大小寫):k,m,g,t,p,e以重新指定大小(例如128k, 512m, 1g等)</description>
</property>

<property>
  <name>dfs.namenode.fs-limits.min-block-size</name>
  <value>1048576</value>
  <description>以字節爲單位的最小塊大小,由Namenode在創建時強制執行時間。這可以防止意外創建帶有小塊的文件可以降級的大小(以及許多塊)的性能。</description>
</property>

<property>
    <name>dfs.namenode.fs-limits.max-blocks-per-file</name>
    <value>1048576</value>
    <description>每個文件的最大塊數,由寫入時的Namenode執行。這可以防止創建會降低性能的超大文件</description>
</property>

HDFS中的NameNode會記錄文件的各個塊都存放在哪個dataNode上,這些信息一般也稱爲元信息(MetaInfo) 。元信息的存儲位置一般由dfs.namenode.name.dir來指定。

<property>
  <name>dfs.namenode.name.dir</name>
  <value>file://${hadoop.tmp.dir}/dfs/name</value>
</property>

而datanode是真實存儲文件塊的節點,塊在datanode的位置一般由dfs.datanode.data.dir來指定。

<property>
  <name>dfs.datanode.data.dir</name>
  <value>file://${hadoop.tmp.dir}/dfs/data</value>
</property>

HDFS上的塊爲什麼遠遠大與傳統文件系統,是有原因的。目的是爲了最小化尋址開銷時間。

HDFS尋址開銷不僅包括磁盤尋道開銷,還包括數據庫的定位開銷,當客戶端需要訪問一個文件時,首先從名稱節點獲取組成這個文件的數據塊的位置列表,然後根據位置列表獲取實際存儲各個數據塊的數據節點的位置,最後,數據節點根據數據塊信息在本地Linux文件系統中找到對應的文件,並把數據返回給客戶端,設計一個比較大的塊,可以把尋址開銷分攤到較多的數據中,相對降低了單位數據的尋址開銷

舉個例子:  塊大小爲128MB,默認傳輸效率100M/s ,尋址時間爲10ms,那麼尋址時間只佔傳輸時間的1%左右  

當然,塊也不能太大,因爲另一個核心技術MapReduce的map任務一次只處理一個數據塊,如果任務太少,勢必會降低工作的並行處理速度。

HDFS的塊概念,在解決了大數據集文件的存儲同時,不僅解決了文件存取的網絡瓶頸問題,還

1、解決了大數據集文件的存儲:大文件分塊存儲在多個數據節點上,不必受限於單個節點的存儲容量。
2、簡化系統設計:塊大小固定,單個節點的塊數量比較少,容易管理。元數據可以單獨由其他系統負責管理。
3、適合數據備份:每個塊可以很容易的冗餘存儲到多個節點上,提高了系統的容錯性和可用性

2、Namenode和Datanode

HDFS集羣上有兩類節點,一類是管理節點(Namenode),一類是工作節點(Datanode)。而HDFS就是以管理節點-工作節點的模式運行的,在HDFS上,通常有一個Namenode和多個Datanode(一個管理者master,多個工作者slave)。

作爲master的NameNode負責管理分佈式文件系統的命名空間(NameSpace),即維護的是文件系統樹及樹內的文件和目錄。這些信息以 兩個核心文件(fsImageeditlog)的形式持久化在本地磁盤中。

fsImage命名空間鏡像文件,用於維護文件系統樹以及文件樹中所有文件和目錄的元數據;操作日誌文件editlog中記錄了所有針對文件的創建、刪除、重命名等操作。namenode也記錄了每個文件的各個塊所在的datanode的位置信息,但並不持久化存儲這些信息,而是在系統每次啓動時掃描所datanode重構得到這些信息,也就是說保存在運行內存中。

Namenode在啓動時,會將FsImage的內容加載到內存當中,然後執行EditLog文件中的各項操作,使得內存中的元數據保持最新。這個操作完成以後,就會創建一個新的FsImage文件和一個空的EditLog文件。名稱節點啓動成功並進入正常運行狀態以後,HDFS中的更新操作都被寫到EditLog,而不是直接寫入FsImage,這是因爲對於分佈式文件系統而言,FsImage文件通常都很龐大,如果所有的更新操作都直接往FsImage文件中添加,那麼系統就會變得非常緩慢。相對而言,EditLog通常都要遠遠小於FsImage,更新操作寫入到EditLog是非常高效的。名稱節點在啓動的過程中處於“安全模式”,只能對外提供讀操作,無法提供寫操作。在啓動結束後,系統就會退出安全模式,進入正常運行狀態,對外提供寫操作。

作爲slave的Datanode是分佈式文件系統HDFS的工作節點,負責數據塊的存儲和讀取(會根據客戶端或者Namenode的調度來進行數據的存儲和檢索),並且定期向Namenode發送自己所存儲的塊的列表。每個Datanode中的數據會被保存在本地Linux文件系統中。

3、SecondaryNamenode

在Namenode運行期間,HDFS會不斷髮生更新操作,這些更新操作不會直接寫到fsimage文件中,而是直接被寫入到editlog文件的,文件會越來越大。當Namenode重啓時,會加載fsimage加載到內存中,並且逐條執行editlog中的記錄,editlog文件大,就會導致整個過程變得非常緩慢,使得Namenode在啓動過程中長期處於“安全模式”,無法正常對外提供寫操作,影響了用戶的使用。

HDFS採用了SecondaryNameNode這個守護線程,可以定期完成editlog與fsImage的合併操作,減小editlog文件大小,縮短Namenode重啓時間;也可以作爲Namenode的一個“檢查點”,將保存Namenode內存中的元數據信息,保存在fsimage鏡像文件中。

---------------------------如有疑問,敬請留意------------------------------------------

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

六、副本概念

HDFS上的塊會進行冗餘存儲,也就是副本策略。因爲hdfs要運行在廉價的硬件之上,出現故障是正常現象,而爲了保證數據的可靠性,數據塊是被複製成多份,當一份數據宕掉後,其餘的可以即刻補上。副本的個數,默認是3。當然可以在hdfs-default.xml中進行修改:

<property>
  <name>dfs.replication</name>
  <value>3</value>
</property>

 那麼,

 

 

 

 

 

 

 

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章