在配置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
- 小結:
-
- 一個檔案被拆成多個block持續化存儲(block size 由配置檔案參數決定) 思考: 修改 block size 對以前持續化的資料有何影響?
- 資料通訊過程中一個 block 被拆成 多個 packet
- 一個 packet 包含多個 chunk
- Packet結構與定義: Packet分為兩類,一類是實際資料包,另一類是heatbeat包。一個Packet資料包的組成結構,如圖所示
- 上圖中,一個Packet是由Header和Data兩部分組成,其中Header部分包含了一個Packet的概要屬性資訊,如下表所示:
- 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
- HDFS Client: 系統使用者,調用HDFS API操作檔案;與NN互動擷取檔案中繼資料;與DN互動進行資料讀寫, 注意:寫資料時檔案切分由Client完成
- Namenode:Master節點(也稱中繼資料節點),是系統唯一的管理者。負責中繼資料的管理(名稱空間和資料塊映射資訊);配置副本政策;處理用戶端請求
- Datanode:資料存儲節點(也稱Slave節點),存儲實際的資料;執行資料塊的讀寫;彙報存儲資訊給NN
- Secondary NameNode:小弟角色,分擔大哥namenode的工作量;是NameNode的冷備份;合并fsimage和fsedits然後再發給namenode, 注意:在hadoop 2.x 版本,當啟用 hdfs ha 時,将沒有這一角色。(詳見第二單)
- 解釋說明:
-
- 熱備份:b是a的熱備份,如果a壞掉。那麼b馬上運作代替a的工作
- 冷備份:b是a的冷備份,如果a壞掉。那麼b不能馬上代替a工作。但是b上存儲a的一些資訊,減少a壞掉之後的損失
- hdfs構架原則:
-
- 中繼資料與資料分離:檔案本身的屬性(即中繼資料)與檔案所持有的資料分離
- 主/從架構:一個HDFS叢集是由一個NameNode和一定數目的DataNode組成
- 一次寫入多次讀取:HDFS中的檔案在任何時間隻能有一個Writer。當檔案被建立,接着寫入資料,最後,一旦檔案被關閉,就不能再修改。
- 移動計算比移動資料更劃算:資料運算,越靠近資料,執行運算的性能就越好,由于hdfs資料分布在不同機器上,要讓網絡的消耗最低,并提高系統的吞吐量,最佳方式是将運算的執行移到離它要處理的資料更近的地方,而不是移動資料
NameNode:
- NameNode是整個檔案系統的管理節點,也是HDFS中最複雜的一個實體,它維護着HDFS檔案系統中最重要的兩個關系:
-
- HDFS檔案系統中的檔案目錄樹,以及檔案的資料塊索引,即每個檔案對應的資料塊清單
- 資料塊和資料節點的對應關系,即某一塊資料塊儲存在哪些資料節點的資訊
- 第一個關系即目錄樹、中繼資料和資料塊的索引資訊會持久化到實體存儲中,實作是儲存在命名空間的鏡像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檔案,該指令需要以下參數:
-
- -i (必填參數) –inputFile <arg> 輸入FSImage檔案
- -o (必填參數) –outputFile <arg> 輸出轉換後的檔案,如果存在,則會覆寫
- -p (可選參數) –processor <arg> 将FSImage檔案轉換成哪種格式: (Ls|XML|FileDistribution).預設為Ls
- 示例:hdfs oiv -i /data1/hadoop/dfs/name/current/fsimage_0000000000019372521 -o /home/hadoop/fsimage.txt
- 指令:hdfs oev (offline edits viewer 離線edits檢視器)的縮寫, 該工具隻操作檔案因而并不需要hadoop叢集處于運作狀态。
-
- 示例: hdfs oev -i edits_0000000000000042778-0000000000000042779 -o edits.xml
- 支援的輸出格式有binary(hadoop使用的二進制格式)、xml(在不使用參數p時的預設輸出格式)和stats(輸出edits檔案的統計資訊)
- 小結:
- NameNode管理着DataNode,接收DataNode的注冊、心跳、資料塊送出等資訊的上報,并且在心跳中發送資料塊複制、删除、恢複等指令;同時,NameNode還為用戶端對檔案系統目錄樹的操作和對檔案資料讀寫、對HDFS系統進行管理提供支援
- Namenode 啟動後會進入一個稱為安全模式的特殊狀态。處于安全模式 的 Namenode 是不會進行資料塊的複制的。 Namenode 從所有的 Datanode 接收心跳信号和塊狀态報告。塊狀态報告包括了某個 Datanode 所有的資料 塊清單。每個資料塊都有一個指定的最小副本數。當 Namenode 檢測确認某 個資料塊的副本數目達到這個最小值,那麼該資料塊就會被認為是副本安全 (safely replicated) 的;在一定百分比(這個參數可配置)的資料塊被 Namenode 檢測确認是安全之後(加上一個額外的 30 秒等待時間), Namenode 将退出安全模式狀态。接下來它會确定還有哪些資料塊的副本沒 有達到指定數目,并将這些資料塊複制到其他 Datanode 上。
Secondary NameNode:在HA cluster中又稱為standby node
- 定期合并 fsimage 和 edits 日志,将 edits 日志檔案大小控制在一個限度下
- 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 (見第四章參數配置)
- Client将FileA按64M分塊。分成兩塊,block1和Block2;
- Client向nameNode發送寫資料請求,如圖藍色虛線①------>
- NameNode節點,記錄block資訊。并傳回可用的DataNode (NameNode按什麼規則傳回DataNode? 參見第三單 hadoop機架感覺),如粉色虛線②--------->
- Block1: host2,host1,host3
- Block2: host7,host8,host4
- client向DataNode發送block1;發送過程是以流式寫入,流式寫入過程如下:
- 将64M的block1按64k的packet劃分
- 然後将第一個packet發送給host2
- host2接收完後,将第一個packet發送給host1,同時client想host2發送第二個packet
- host1接收完第一個packet後,發送給host3,同時接收host2發來的第二個packet
- 以此類推,如圖紅線實線所示,直到将block1發送完畢
- host2,host1,host3向NameNode,host2向Client發送通知,說“消息發送完了”。如圖粉紅顔色實線所示
- client收到host2發來的消息後,向namenode發送消息,說我寫完了。這樣就真完成了。如圖黃色粗實線
- 發送完block1後,再向host7,host8,host4發送block2,如圖藍色實線所示
- 說明:
-
- 當用戶端向 HDFS 檔案寫入資料的時候,一開始是寫到本地臨時檔案中。假設該檔案的副 本系數設定為 3 ,當本地臨時檔案累積到一個資料塊的大小時,用戶端會從 Namenode 擷取一個 Datanode 清單用于存放副本。然後用戶端開始向第一個 Datanode 傳輸資料,第一個 Datanode 一小部分一小部分 (4 KB) 地接收資料,将每一部分寫入本地倉庫,并同時傳輸該部分到清單中 第二個 Datanode 節點。第二個 Datanode 也是這樣,一小部分一小部分地接收資料,寫入本地 倉庫,并同時傳給第三個 Datanode 。最後,第三個 Datanode 接收資料并存儲在本地。是以, Datanode 能流水線式地從前一個節點接收資料,并在同時轉發給下一個節點,資料以流水線的 方式從前一個 Datanode 複制到下一個
- 時序圖如下:
- 小結:
- 寫入的過程,按hdsf預設設定,1T檔案,我們需要3T的存儲,3T的網絡流量
- 在執行讀或寫的過程中,NameNode和DataNode通過HeartBeat進行儲存通信,确定DataNode活着。如果發現DataNode死掉了,就将死掉的DataNode上的資料,放到其他節點去。讀取時,要讀其他節點去
- 挂掉一個節點,沒關系,還有其他節點可以備份;甚至,挂掉某一個機架,也沒關系;其他機架上,也有備份
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持久化到磁盤上的實體存儲結構,如下圖所示:
- 每個Block檔案(如上圖中blk_1084013198檔案)都對應一個meta檔案(如上圖中blk_1084013198_10273532.meta檔案),Block檔案是一個一個Chunk的二進制資料(每個Chunk的大小是512位元組),而meta檔案是與每一個Chunk對應的Checksum資料,是序列化形式存儲