天天看點

hadoop(一):深度剖析hdfs原理 - 天戈朱

       在配置hbase叢集将 hdfs 挂接到其它鏡像盤時,有不少困惑的地方,結合以前的資料再次學習;  大資料底層技術的三大基石起源于Google在2006年之前的三篇論文GFS、Map-Reduce、 Bigtable,其中GFS、Map-Reduce技術直接支援了Apache Hadoop項目的誕生,Bigtable催生了NoSQL這個嶄新的資料庫領域,由于map-Reduce處理架構高延時的缺陷, Google在2009年後推出的Dremel促使了實時計算系統的興起,以此引發大資料第二波技術浪潮,一些大資料公司紛紛推出自己的大資料查詢分析産品,如:Cloudera開源了大資料查詢分析引擎Impala、Hortonworks開源了 Stinger、Fackbook開源了Presto、UC Berkeley AMPLAB實驗室開發了Spark計算架構,所有這些技術的資料來源均基于hdsf, 對于 hdsf 最基本的不外乎就是其讀寫操作

目錄:

  • hdfs 名詞解釋
  • hdsf 架構
  • NameNode(NN)
  • Secondary NN
  • hdfs 寫檔案
  • hdfs 讀檔案
  • block持續化結構

HDFS名詞解釋:

  • Block: 在HDFS中,每個檔案都是采用的分塊的方式存儲,每個block放在不同的datanode上,每個block的辨別是一個三元組(block id, numBytes,generationStamp),其中block id是具有唯一性,具體配置設定是由namenode節點設定,然後再由datanode上建立block檔案,同時建立對應block meta檔案
  • Packet:在DFSclient與DataNode之間通信的過程中,發送和接受資料過程都是以一個packet為基礎的方式進行
  • Chunk:中文名字也可以稱為塊,但是為了與block區分,還是稱之為chunk。在DFSClient與DataNode之間通信的過程中,由于檔案采用的是基于塊的方式來進行的,但是在發送資料的過程中是以packet的方式來進行的,每個packet包含了多個chunk,同時對于每個chunk進行checksum計算,生成checksum bytes
  • 小結:
    1. 一個檔案被拆成多個block持續化存儲(block size 由配置檔案參數決定)   思考: 修改 block size 對以前持續化的資料有何影響?
    2. 資料通訊過程中一個 block 被拆成 多個 packet
    3. 一個 packet 包含多個 chunk
  • Packet結構與定義: Packet分為兩類,一類是實際資料包,另一類是heatbeat包。一個Packet資料包的組成結構,如圖所示
  • hadoop(一):深度剖析hdfs原理 - 天戈朱
  • 上圖中,一個Packet是由Header和Data兩部分組成,其中Header部分包含了一個Packet的概要屬性資訊,如下表所示:
  • hadoop(一):深度剖析hdfs原理 - 天戈朱
  • Data部分是一個Packet的實際資料部分,主要包括一個4位元組校驗和(Checksum)與一個Chunk部分,Chunk部分最大為512位元組
  • 在建構一個Packet的過程中,首先将位元組流資料寫入一個buffer緩沖區中,也就是從偏移量為25的位置(checksumStart)開始寫Packet資料Chunk的Checksum部分,從偏移量為533的位置(dataStart)開始寫Packet資料的Chunk Data部分,直到一個Packet建立完成為止。
  • 當寫一個檔案的最後一個Block的最後一個Packet時,如果一個Packet的大小未能達到最大長度,也就是上圖對應的緩沖區中,Checksum與Chunk Data之間還保留了一段未被寫過的緩沖區位置,在發送這個Packet之前,會檢查Chunksum與Chunk Data之間的緩沖區是否為空白緩沖區(gap),如果有則将Chunk Data部分向前移動,使得Chunk Data 1與Chunk Checksum N相鄰,然後才會被發送到DataNode節點

hdsf架構:

  • hdfs的構架圖網上一堆,抓了一張表述比較清楚的圖如下, 主要包含因類角色:Client、NameNode、SecondayNameNode、DataNode
  • hadoop(一):深度剖析hdfs原理 - 天戈朱
  • HDFS Client: 系統使用者,調用HDFS API操作檔案;與NN互動擷取檔案中繼資料;與DN互動進行資料讀寫, 注意:寫資料時檔案切分由Client完成 
  • Namenode:Master節點(也稱中繼資料節點),是系統唯一的管理者。負責中繼資料的管理(名稱空間和資料塊映射資訊);配置副本政策;處理用戶端請求
  • Datanode:資料存儲節點(也稱Slave節點),存儲實際的資料;執行資料塊的讀寫;彙報存儲資訊給NN
  • Secondary NameNode:小弟角色,分擔大哥namenode的工作量;是NameNode的冷備份;合并fsimage和fsedits然後再發給namenode, 注意:在hadoop 2.x 版本,當啟用 hdfs ha 時,将沒有這一角色。(詳見第二單)
  • 解釋說明:
    1. 熱備份:b是a的熱備份,如果a壞掉。那麼b馬上運作代替a的工作
    2. 冷備份:b是a的冷備份,如果a壞掉。那麼b不能馬上代替a工作。但是b上存儲a的一些資訊,減少a壞掉之後的損失
  • hdfs構架原則:
    1. 中繼資料與資料分離:檔案本身的屬性(即中繼資料)與檔案所持有的資料分離
    2. 主/從架構:一個HDFS叢集是由一個NameNode和一定數目的DataNode組成
    3. 一次寫入多次讀取:HDFS中的檔案在任何時間隻能有一個Writer。當檔案被建立,接着寫入資料,最後,一旦檔案被關閉,就不能再修改。
    4. 移動計算比移動資料更劃算:資料運算,越靠近資料,執行運算的性能就越好,由于hdfs資料分布在不同機器上,要讓網絡的消耗最低,并提高系統的吞吐量,最佳方式是将運算的執行移到離它要處理的資料更近的地方,而不是移動資料

NameNode:

  • NameNode是整個檔案系統的管理節點,也是HDFS中最複雜的一個實體,它維護着HDFS檔案系統中最重要的兩個關系:
    1. HDFS檔案系統中的檔案目錄樹,以及檔案的資料塊索引,即每個檔案對應的資料塊清單
    2. 資料塊和資料節點的對應關系,即某一塊資料塊儲存在哪些資料節點的資訊
  • 第一個關系即目錄樹、中繼資料和資料塊的索引資訊會持久化到實體存儲中,實作是儲存在命名空間的鏡像fsimage和編輯日志edits中,注意:在fsimage中,并沒有記錄每一個block對應到哪幾個Datanodes的對應表資訊
  • 第二個關系是在NameNode啟動後,每個Datanode對本地磁盤進行掃描,将本Datanode上儲存的block資訊彙報給Namenode,Namenode在接收到每個Datanode的塊資訊彙報後,将接收到的塊資訊,以及其所在的Datanode資訊等儲存在記憶體中。HDFS就是通過這種塊資訊彙報的方式來完成 block -> Datanodes list的對應表建構
  • fsimage記錄了自最後一次檢查點之前HDFS檔案系統中所有目錄和檔案的序列化資訊;
  • edits是中繼資料記錄檔(記錄每次儲存fsimage之後到下次儲存之間的所有hdfs操作)
  • 在NameNode啟動時候,會先将fsimage中的檔案系統中繼資料資訊加載到記憶體,然後根據eidts中的記錄将記憶體中的中繼資料同步至最新狀态,将這個新版本的 FsImage 從記憶體中儲存到本地磁盤上,然後删除 舊的 Editlog,這個過程稱為一個檢查 點 (checkpoint), 多長時間做一次 checkpoint?(見第四章 參數配置) checkpoint 能手工觸發嗎? 驗證重新開機hdfs服務後editlog沒删除呢?
  • 類似于資料庫中的檢查點,為了避免edits日志過大,在Hadoop1.X中,SecondaryNameNode會按照時間門檻值(比如24小時)或者edits大小門檻值(比如1G),周期性的将fsimage和edits的合并,然後将最新的fsimage推送給NameNode。而在Hadoop2.X中,這個動作是由Standby NameNode來完成.
  • 由此可看出,這兩個檔案一旦損壞或丢失,将導緻整個HDFS檔案系統不可用,在HDP2.4安裝(五):叢集及元件安裝  叢集安裝過程中,hdfs 預設的隻能選擇一個NN,是否意味着NN存在單點呢?(見第二單 hdfs HA)
  • 在hadoop1.X為了保證這兩種中繼資料檔案的高可用性,一般的做法,将dfs.namenode.name.dir設定成以逗号分隔的多個目錄,這多個目錄至少不要在一塊磁盤上,最好放在不同的機器上,比如:挂載一個共享檔案系統
  • fsimage\edits 是序列化後的檔案,想要檢視或編輯裡面的内容,可通過 hdfs 提供的 oiv\oev 指令,如下:
    • 指令: hdfs oiv (offline image viewer) 用于将fsimage檔案的内容轉儲到指定檔案中以便于閱讀,,如文本檔案、XML檔案,該指令需要以下參數:
      1. -i  (必填參數)  –inputFile <arg>  輸入FSImage檔案
      2. -o (必填參數)  –outputFile <arg> 輸出轉換後的檔案,如果存在,則會覆寫
      3. -p (可選參數) –processor <arg>   将FSImage檔案轉換成哪種格式: (Ls|XML|FileDistribution).預設為Ls
      4. 示例:hdfs oiv -i /data1/hadoop/dfs/name/current/fsimage_0000000000019372521 -o /home/hadoop/fsimage.txt
    • 指令:hdfs oev (offline edits viewer 離線edits檢視器)的縮寫, 該工具隻操作檔案因而并不需要hadoop叢集處于運作狀态。
      1. 示例:  hdfs oev -i edits_0000000000000042778-0000000000000042779 -o edits.xml
      2. 支援的輸出格式有binary(hadoop使用的二進制格式)、xml(在不使用參數p時的預設輸出格式)和stats(輸出edits檔案的統計資訊)
  • 小結:
  1. NameNode管理着DataNode,接收DataNode的注冊、心跳、資料塊送出等資訊的上報,并且在心跳中發送資料塊複制、删除、恢複等指令;同時,NameNode還為用戶端對檔案系統目錄樹的操作和對檔案資料讀寫、對HDFS系統進行管理提供支援
  2. Namenode 啟動後會進入一個稱為安全模式的特殊狀态。處于安全模式 的 Namenode 是不會進行資料塊的複制的。 Namenode 從所有的 Datanode 接收心跳信号和塊狀态報告。塊狀态報告包括了某個 Datanode 所有的資料 塊清單。每個資料塊都有一個指定的最小副本數。當 Namenode 檢測确認某 個資料塊的副本數目達到這個最小值,那麼該資料塊就會被認為是副本安全 (safely replicated) 的;在一定百分比(這個參數可配置)的資料塊被 Namenode 檢測确認是安全之後(加上一個額外的 30 秒等待時間), Namenode 将退出安全模式狀态。接下來它會确定還有哪些資料塊的副本沒 有達到指定數目,并将這些資料塊複制到其他 Datanode 上。

Secondary NameNode:在HA cluster中又稱為standby node

  • 定期合并 fsimage 和 edits 日志,将 edits 日志檔案大小控制在一個限度下
  • hadoop(一):深度剖析hdfs原理 - 天戈朱
  • namenode 響應 Secondary namenode 請求,将 edit log 推送給 Secondary namenode , 開始重新寫一個新的 edit log
  • Secondary namenode 收到來自 namenode 的 fsimage 檔案和 edit log
  • Secondary namenode 将 fsimage 加載到記憶體,應用 edit log , 并生成一 個新的 fsimage 檔案
  • Secondary namenode 将新的 fsimage 推送給 Namenode
  • Namenode 用新的 fsimage 取代舊的 fsimage , 在 fstime 檔案中記下檢查 點發生的時

 HDFS寫檔案:

  • 寫檔案部分參考blog 位址 (http://www.cnblogs.com/laov/p/3434917.html),2.X版本預設block的大小是 128M (見第四章參數配置)
  • hadoop(一):深度剖析hdfs原理 - 天戈朱
  1. Client将FileA按64M分塊。分成兩塊,block1和Block2;
  2. Client向nameNode發送寫資料請求,如圖藍色虛線①------>
  3. NameNode節點,記錄block資訊。并傳回可用的DataNode (NameNode按什麼規則傳回DataNode? 參見第三單 hadoop機架感覺),如粉色虛線②--------->
    • Block1: host2,host1,host3
    • Block2: host7,host8,host4
  4. client向DataNode發送block1;發送過程是以流式寫入,流式寫入過程如下:
    1. 将64M的block1按64k的packet劃分
    2. 然後将第一個packet發送給host2
    3. host2接收完後,将第一個packet發送給host1,同時client想host2發送第二個packet
    4. host1接收完第一個packet後,發送給host3,同時接收host2發來的第二個packet
    5. 以此類推,如圖紅線實線所示,直到将block1發送完畢
    6. host2,host1,host3向NameNode,host2向Client發送通知,說“消息發送完了”。如圖粉紅顔色實線所示
    7. client收到host2發來的消息後,向namenode發送消息,說我寫完了。這樣就真完成了。如圖黃色粗實線
    8. 發送完block1後,再向host7,host8,host4發送block2,如圖藍色實線所示
  •  說明:
    1. 當用戶端向 HDFS 檔案寫入資料的時候,一開始是寫到本地臨時檔案中。假設該檔案的副 本系數設定為 3 ,當本地臨時檔案累積到一個資料塊的大小時,用戶端會從 Namenode 擷取一個 Datanode 清單用于存放副本。然後用戶端開始向第一個 Datanode 傳輸資料,第一個 Datanode 一小部分一小部分 (4 KB) 地接收資料,将每一部分寫入本地倉庫,并同時傳輸該部分到清單中 第二個 Datanode 節點。第二個 Datanode 也是這樣,一小部分一小部分地接收資料,寫入本地 倉庫,并同時傳給第三個 Datanode 。最後,第三個 Datanode 接收資料并存儲在本地。是以, Datanode 能流水線式地從前一個節點接收資料,并在同時轉發給下一個節點,資料以流水線的 方式從前一個 Datanode 複制到下一個
    2. 時序圖如下:
hadoop(一):深度剖析hdfs原理 - 天戈朱
  •  小結:
    1. 寫入的過程,按hdsf預設設定,1T檔案,我們需要3T的存儲,3T的網絡流量
    2. 在執行讀或寫的過程中,NameNode和DataNode通過HeartBeat進行儲存通信,确定DataNode活着。如果發現DataNode死掉了,就将死掉的DataNode上的資料,放到其他節點去。讀取時,要讀其他節點去
    3. 挂掉一個節點,沒關系,還有其他節點可以備份;甚至,挂掉某一個機架,也沒關系;其他機架上,也有備份

hdfs讀檔案: 

  •  讀到檔案示意圖如下:
  • hadoop(一):深度剖析hdfs原理 - 天戈朱
  • 用戶端通過調用FileSystem對象的open()方法來打開希望讀取的檔案,對于HDFS來說,這個對象時分布檔案系統的一個執行個體;
  • DistributedFileSystem通過使用RPC來調用NameNode以确定檔案起始塊的位置,同一Block按照重複數會傳回多個位置,這些位置按照Hadoop叢集拓撲結構排序,距離用戶端近的排在前面 (詳見第三章)
  • 前兩步會傳回一個FSDataInputStream對象,該對象會被封裝成DFSInputStream對象,DFSInputStream可以友善的管理datanode和namenode資料流,用戶端對這個輸入流調用read()方法
  • 存儲着檔案起始塊的DataNode位址的DFSInputStream随即連接配接距離最近的DataNode,通過對資料流反複調用read()方法,将資料從DataNode傳輸到用戶端
  • 到達塊的末端時,DFSInputStream會關閉與該DataNode的連接配接,然後尋找下一個塊的最佳DataNode,這些操作對用戶端來說是透明的,用戶端的角度看來隻是讀一個持續不斷的流
  • 一旦用戶端完成讀取,就對FSDataInputStream調用close()方法關閉檔案讀取

block持續化結構:

  •  DataNode節點上一個Block持久化到磁盤上的實體存儲結構,如下圖所示:
  • hadoop(一):深度剖析hdfs原理 - 天戈朱
  • 每個Block檔案(如上圖中blk_1084013198檔案)都對應一個meta檔案(如上圖中blk_1084013198_10273532.meta檔案),Block檔案是一個一個Chunk的二進制資料(每個Chunk的大小是512位元組),而meta檔案是與每一個Chunk對應的Checksum資料,是序列化形式存儲
hadoop(一):深度剖析hdfs原理 - 天戈朱