1. 程式人生 > >【圖文詳解】HDFS基本原理

【圖文詳解】HDFS基本原理

合並操作 ear 系統性能 重要 logs 允許 積累 帶寬 文件系統

本文主要詳述了HDFS的組成結構,客戶端上傳下載的過程,以及HDFS的高可用和聯邦HDFS等內容。若有不當之處還請留言指出。

當數據集大小超過一臺獨立的物理計算機的存儲能力時,就有必要對它進行分區,並存儲到若幹臺獨立的計算機上。Hdfs是Hadoop中的大規模分布式文件存儲系統。

HDFS的特點

  • HDFS文件系統可存儲超大文件

1)HDFS是一種文件系統,自身也有塊(block)的概念,其文件塊要比普通單一磁盤上文件系統大的多,hadoop1.0上默認是 64MB,2.0默認是128MB。與其他文件系統不同的是,HDFS中小於一個塊大小的文件不會占據整個塊的空間。

2)HDFS上的塊之所以設計的如此之大,其目的是為了最小化尋址開銷。如果塊設置得足夠大,從磁盤傳輸數據的時間會明顯大於定位這個塊開始位置所需的時間。

3)HDFS文件的所有塊並不需要存儲在一個磁盤上,因此可以利用集群上任意一個磁盤進行存儲,由於具備這種分布式存儲的邏輯,所以可以存儲超大的文件。

  • HDFS同一時刻只允許一個客戶端對文件進行追加寫操作(不支持多個寫入者的操作,也不支持在文件的任意位置修改),這樣避免了復雜的並發管理功能,但也限制了系統性能。

  • 運行在普通廉價的機器上

Hadoop 的設計對硬件要求低,無需昂貴的高可用性機器上,因為在 HDFS 設計中充分考慮到了數據的可靠性、安全性和高可用性。

  • HDFS適合存儲大文件並為之提供高吞吐量的順序讀/寫操作,不太適合大量隨機讀的應用場景,也不適合存大量小文件的應用場景。HDFS是為高吞吐量應用優化的,會以提高時間延遲為代價,因此不適合處理低時延的數據訪問的應用。

HDFS體系架構

  • HDFS 是一個主/從(Master/Slave)體系架構,由於分布式存儲的性質,集群擁有兩類節點 NameNode 和 DataNode。

  • NameNode(名稱節點):系統中通常只有一個,中心服務器的角色,管理存儲和檢索多個 DataNode 的實際數據所需的所有元數據,響應客戶請求。

  • DataNode(數據節點):系統中通常有多個,是文件系統中真正存儲數據的地方,在NameNode 統一調度下進行數據塊的創建、刪除和復制。

NameNode

NameNode負責整個分布式文件系統的元數據,包括文件目錄樹,文件到數據塊Block的映射關系等。這些數據保存在內存裏,同時這些數據還以兩個文件形式永久保存在本地磁盤上:命名空間鏡像文件(fsimage)和編輯日誌文件(editlog)。fsimage是內存命名空間元數據在外存的鏡像文件,editlog文件則記錄著用戶對文件的各種操作記錄,當客戶端對hdfs中的文件進行新增或者修改操作,操作記錄首先被記入editlog文件中,當客戶端操作成功後,相應的元數據會更新到內存meta.data中,防止發生意外導致丟失內存中的數據。fsimage和editlog兩個文件結合可以構造出完整的內存數據。

NameNdoe還負責對DataNode的狀態監控。DataNode定期向NameNode發送心跳以及所存儲的塊的列表信息。NameNode可以知道每個DataNode上保存著哪些數據(Block信息),DataNode是否存活,並可以控制DataNode啟動或是停止。若NameNode發現某個DataNode發生故障,會將其存儲的數據在其他DataNode機器上增加相應的備份以維護數據副本(默認為3,可在配置文件中配置)保持不變。

如果NaneNode服務器失效,集群將失去所有的數據。因為我們將無從知道哪些DataNode存儲著哪些數據。因此NameNode的高可用,容錯機制很重要。

DataNode

DataNode負責數據塊的實際存儲和讀/寫工作。在hadoop1.0時,DataNode的數據塊默認大小為64M,2.0版本後,塊的默認大小為128M。當客戶端上傳一個大文件時,HDFS會自動將其切割成固定大小的Block,每個塊以多份的形式存儲在集群上,默認為3份。

  • Datanode掉線判斷

datanode進程死亡或者網絡故障造成datanode無法與namenode通信,namenode不會立即把該節點判定為死亡,要經過一段時間,這段時間暫稱作超時時長。HDFS默認的超時時長為10分鐘+30秒。如果定義超時時間為timeout,則超時時長的計算公式為:

timeout  = 2 * heartbeat.recheck.interval + 10 * dfs.heartbeat.interval
而默認的heartbeat.recheck.interval 大小為5分鐘,dfs.heartbeat.interval默認為3秒。
需要註意的是hdfs-site.xml 配置文件中的heartbeat.recheck.interval的單位為毫秒,dfs.heartbeat.interval的單位為秒。

配置文件

<property>
        #NameNode向DataNode發起的請求,要求其發送心跳信息的時間間隔
        <name>heartbeat.recheck.interval</name>
        <value>8000</value>
</property>
<property>
        #DataNode發送心跳的時間間隔
        <name>dfs.heartbeat.interval</name>
        <value>3</value>
</property>
  • 數據副本塊數量與默認數量不同

    <property>
    #DataNode默認60分鐘向NameNode提交自己的Block信息
    <name>dfs.blockreport.intervalMsec</name>
    <value>3600000</value>
    </property>

    如果一臺DataNode經過10分30秒(默認)後沒有給NameNode發送心跳信息,而被NameNode判斷為死亡,NameNode會馬上將其上的數據備份到集群中其他機器上。當這個DataNode節點排除故障後,重新回到集群中,該節點上還保存著原來那批數據,而默認的配置情況下,DataNode會每隔60分鐘向NameNode發送一次Block信息,在這段時間內,集群中會有某些數據塊多出一個備份。在NameNode收到該節點的Block信息後,它發現數據備份多了才會命令某些DataNode刪除掉多余的備份數據。

客戶端上傳文件

技術分享圖片

步驟詳解:

1)向namenode請求上傳文件

2)namenode檢查客戶端要求上傳的文件是否已存在,父目錄是否存在

3)namenode響應客戶端是否可以上傳文件

4)若第3步獲得可以上傳的信息,客戶端向namenode發出請求,詢問第一塊block該上傳到哪裏

5)namenode查詢datanode信息(忙碌情況,遠近情況等)

6)namenode返回3個datanode地址給客戶端

7)客戶端請求與最近的一個datanode節點(假設為datanode1)建立傳輸通道,並告知其還要傳給datanode2和datanode3。datanode1會請求與datanode2建立連接,datanode2會請求與datanode3建立連接。

8)datanode3響應datanode2的連接請求,通道建立成功。同理,datanode2響應datanode1,datanode1響應客戶端。

9)客戶端收到通道建立成功的消息後,開始向datanode1發送block1的數據,以一個個package(64k)為單位通過通道向datanode1寫數據,datanode1收到數據會將其存在本地緩存中,一邊向datanode2傳數據,一邊將緩存中的數據保存到磁盤上。

10)客戶端在傳送數據時會有一個package的應答隊列,datanode1每收到一個package後就向客戶端發回消息(datanode1不用等待datandoe2發回應答信息才給客戶端發送信息,客戶端只保證datanode1收到了數據就行,後面的事它交給了datanode1)

11)當一個block傳輸完成之後,客戶端再次請求namenode上傳第二個block

NameNode如何選擇DataNode

技術分享圖片

客戶端在上傳數據時,請求namenode告訴其應該往哪幾個datanode上傳副本。namenode需要綜合考慮datanode的可靠性,寫入帶寬,讀出帶寬等因素。默認情況下,在運行客戶端的那個節點上存放第1個副本,如果客戶端運行在集群之外,則隨機選擇一個節點存放第1塊,但namenode會盡量選擇那些情況好的datanode(存儲不太滿,當時不太忙,帶寬比較高)。第2個副本存放在與第1個副本所在機架不同的另一個機架上的datanode中(隨機選擇另一機架上的另一情況較好的datanode),第3個副本存在與第2個副本相同機架但不同datanode的另一個datanode上。

所有有關塊復制的決策統一由 NameNode 負責,NameNode 會周期性地接受集群中數據節點 DataNode 的心跳和塊報告。一個心跳的到達表示這個數據節點是正常的。一個塊報告包括該數據節點上所有塊的列表。

客戶端下載文件

技術分享圖片

步驟詳解:

1)跟namenode通信,請求下載某個數據。

2)namenode查詢元數據信息以及block位置信息。

3)將數據所在的datanode信息返回給客戶端。

4)客戶端根據數據所在的datanode,挑選一臺距離自己最近的datanode,並向其發出下載文件的請求(若所需數據不在一臺datanode上保存,則分別向多臺datanode發出請求)。

5)datanode響應客戶端請求,將數據返回給客戶端。

6)從多個datanode獲得的數據不斷在客戶端追加,形成完整的數據

NameNode與Secondary NameNode

因為namenode上保存著整個hdfs集群上的所有元數據信息,如果namenode宕機,集群將失去所有數據,因此對namenode實現容錯十分重要,Hadoop為此提供了兩種機制。

第一種是在配置文件裏配置namenode的工作目錄為多個,這樣可以將元數據信息存到多塊磁盤上,或是多臺機器上,甚至可以將元數據存在遠程掛載的網絡文件系統中(NFS),可以通過配置使namenode在多個文件系統上實時保存元數據。這樣一來,namenode的工作目錄所在的磁盤損壞後,還有其他磁盤上的數據可用。

第二種是運行一個輔助namenode,被稱為secondary namenode(第二名稱節點)。secondary namenode的職責並不是作為namenode的熱備份機,其主要作用是定期從namenode拉取fsimage和editlog,並將兩者合並成新的fsimage,將新的fsimage返回給namenade。這種方式,一方面可以避免namenode上的編輯日誌過大,另一方面將合並操作放在secondary namenode上可以節省namenode的cpu時間和內存,減輕namenode的工作壓力,讓namenode更專註於自己的本職工作。secondary namenode中保存的fsimage數據總是會滯後於namenode內存中的元數據,所以在namenode宕機後,難免會有部分的數據丟失。(可以把NFS上的namenode元數據復制到secondary namenode上,使其成為新的namenode,並不損失任何數據)

Secondary NameNode的工作

secondary namenode將namenode上積累的所有editlog下載到本地,並加載到內存進行merge,這個過程稱為checkpoint。

技術分享圖片

步驟詳解:

1)secondary namenode通知namenode要進行checkpoint了。(定時,或是namenode上的editlog數量達到一定規模)。

2)namenode做準備。

3)secondary namenode將namenode的editlogs下載到本地磁盤上。

4)secondary namenode將editlogs和fsimage加載到內存中,進行合並產生新的fsimage。

5)secondary namenode將新的fsimage傳回給namenode(覆蓋namenode上舊的fsimage文件),並將其保存到本地磁盤上覆蓋掉舊的fsimage。

註意點:

  • a表示,hdfs上數據的更新修改等操作都會先寫入編輯日誌文件,再更新到內存裏。
  • secondary namenode節點只有在啟動後,第一次進行checkpoint時才會將namenode的editlog和fsimage都下載到自己的本地磁盤,再進行合並。後期的checkpoint都只會下載editlog文件,而不會下載fsimage,因為自己磁盤上保存的fsimage和namenode上的是一樣的。

NameNode高可用(High Availability,HA)

即使將namenode內存中的元數據備份在多個文件系統中,並通過secondary namenode的checkpoint功能防止namenode的數據丟失,但依然無法實現namenode的高可用。namenode一旦失效,整個系統將無法提供服務,管理員通過冷啟動的方式讓新的namenode上線需要一段等待的時間(幾十分鐘,甚至更長)。新的namenode在響應服務前必須經歷以下以下步驟:將元數據導入內存;重做編輯日誌文件;接收到足夠多的來自datanode的數據塊報告並退出安全模式(數據塊的位置信息不保存在元數據中,需要namenode啟動時在datanode向其匯報的塊信息中獲取)。

針對以上問題,hadoop的2.x版本提出了namenode的HA解決方案。
技術分享圖片

1)主控服務器由一主(Active NameNode,ANN)一從(Standby NameNode,SNN)兩臺服務器構成。

2)ANN響應客戶端請求,SNN作為ANN的熱備份機,同步ANN保存的元數據,在ANN失效時轉換成新的ANN,快速提供服務。

3)ANN和SNN之間通過高可用的共享存儲系統保持數據一致(ANN將數據寫入共享存儲系統,SNN一直監聽共享系統,一旦數據發生改變就將其加載到自己內存中)

4)datanode同時向ANN和SNN匯報心跳和block信息。

5)故障轉移控制器(Failover Contraller,FC),監控ANN和SNN的狀態,並不斷向ZK集群匯報心跳信息。

6)ZK集群"選舉領導者",一旦發現ANN失效,就重新選舉SNN作為新的領導者,FC通知其轉變為新的ANN。Hadoop剛啟動時,兩臺NameNode都是SNN,zk集群通過選舉產生領導者作為ANN。

NameNode聯盟(聯邦HDFS)

技術分享圖片

1)namenode的內存數據包括兩塊內容,命名空間和數據塊池(在namenode聯盟中這兩塊數據相加被稱為命名空間卷)。

2)命名空間中保存的內容包括文件或目錄的擁有者,修改日期,以及文件被切分為哪幾個塊等信息,但不包括塊到底是存儲在哪些datanode中的信息(block位置信息)。

3)數據塊池中保存著block位置信息(namenode剛啟動時並沒有block位置信息,是由datanode向其發送的block塊信息中獲取的)

4)datanode很好地支持水平擴展,但單一namenode受內存空間限制,使得HDFS中所能容納的最大文件數量受到限制(一個大文件和一個小文件的元數據所占內存空間大小是基本相同,所以不適合存小文件,會很快占滿namenode的內存)。

5)單一namanode使得所有來自客戶端的請求都由一臺服務器響應,很容易達到其性能上線,無法實現性能上的水平擴展。

6)單一namenode無法隔離來自不同客戶的請求(比如本地實驗時,對namenode的負載影響會導致正常用戶的訪問請求受到延遲等)

由於單一namenode存在以上4,5,6所述的問題,hadoop2.0給出了namenode聯盟的解決方案,實現對namenode的水平擴展。

技術分享圖片

1)將一個大的命名空間切割成若幹子命名空間,每個namenode管理命名空間中的一部分(如一個namenode管理/user下的所有文件,另一個管理/test下的所有文件)。

2)每個namenode單獨管理自己的命名空間和數據塊池(也可將所有數據塊池抽離出來,由另外的服務器集群來擔任此功能),兩兩之間不進行通信,一個namenode宕機不會影響其他namenode工作。

3)所有datanode被所有namenode共享,還是擔任存儲數據的功能。每個數據塊的信息保存在唯一的某個數據塊池中。

4)所有datanode都要註冊每一個namenode,為每個namenode提供存儲數據的服務。

5)每個datanode向所有的namenode發送心跳和block信息,每個namenode再根據自己的子命名空間維護自己的數據塊池。

【圖文詳解】HDFS基本原理