HDFS結構
概述:
是Hadoop項目的核心子項目。是分布式計算中數據存儲管理的基礎,是基於流數據模式訪問和處理超大文件的需求而開發的,可以運行於廉價的商用服務器上 pc server
高容錯性 :自動保存多個副本來增加容錯性
如果某一個副本丟失,HDFS機制會復制其他機器上的副本,透明實現
支持超大文件
流式數據訪問 批量處理不是用戶交互式處理
HDFS使應用程序能夠以流的形式訪問數據 注重的是吞吐量而不是數據訪問的速度
簡化的一致性模型
大部分為一次寫入多次讀取
系統架構
客戶端:實現文件的切分 將文件切分成多個block數據塊
只有可以切分才可以分布式存儲
與namenode交互,獲取文件的位置信息
跟datanode交互,讀取對應的數據塊
管理和訪問HDFS
命令
NameNode master
管理HDFS的名稱空間 維護目錄結構
(這些信息以兩種形式存在本地文件系統中 一種是命名空間的鏡像文件File Systerm鏡像文件 另一種命名空間鏡像編輯日志 Edit Log
管理數據塊的映射關系
配置副本策略 提高容錯性
客戶端的讀寫請求
dataNode slave
存儲實際的數據塊
執行數據塊的讀/寫操作
數據塊 每個數據塊都有多個副本 這些副本被分布在多個datanode上
是HDFS的最小存儲單元
元數據
是文件系統中文件和目錄的信息以及文件和block的對應關系
HDFS 高可用原理
一個namnode會出錯,所以還有一個備用的namenode
NFS:也是共享文件,正在使用的namenode掛了,則備用的就從NFS里獲取數據
但是如果因為網絡原因的話可能會產生數據不同步問題
QJM :通過一組journalnode共享數據 使用的namenode往journeynode
寫數據。寫成功一半則備用的namenode開始同步數據
HDFS HA-Namenode工作原理
無論什么時候都只能有一個namenode來提供狀態
在任何時候Active的Namenode掛掉時能夠第一時間接替它的任務成為主Namenode,達到一個熱備份的效果
當發生故障時,備用的namenode會在它成為active namenode前讀取所有的journalnode里面的修改日志,這樣就能高可靠的保證與掛掉的namenode的目錄鏡像樹一致,然后無縫接替其職責
為了達到高容錯性的目的,備用角色也會接受來自datanode角色匯報的塊信息
zkfc對namenode的主備切換進行總體控制,能及時檢測到namenode的健康狀況
在主namenode故障時借助zookeeper實現自動的主備選舉和切換,每個運行在namenode的機器都會運行一個zkfc
zkfc作用:
namenode健康狀況監控:
zkfc定期以RPC的方式向本地的namenode發送健康檢查命令
只要namenode及時回復自己是健康的,那么zkfc認為那么濃的是健康的。如果namenode卡死,則zkfc則認為其不健康
zk會話管理:
當本地的namenode是健康的,zkfc則以心跳的方式保持一個會話,如果本地的namenode是active,zkfc也在zk上持有一個特殊的lock znode,如果zkfc檢測到namenode是不健康的,則停止向zk上報心跳,會話失效,lock node過期刪除
ZK選舉
如果本地的namenode是健康的,zkfc也沒有看到其他namenode持有lock znode。它將試着獲取lock znode,如果成功則贏得了選舉,則它本地的namenode變為active
zkfc是一個獨立的進程
為什么不和NN在一起?
防止因為NN的垃圾回收失敗導致心跳受影響
FailoverController功能的代碼應該和應用分離,提高容錯性
使得主備選舉成為可插拔式的插件
QJM:
namenode記錄了HDFS的目錄文件等元數據,客戶端每次對文件的增刪改查等操作,namenode會記錄一條日志,叫做editlog,而元數據存儲在fsimage中,為了保持備用和active的狀態一直,備用的需要盡量實時獲取每條editlog日志,並應用到Fsimage。這時需要一個共享存儲存放editlog,備用的可以實時獲取日志
有兩個關鍵點需要保證:
共享存儲是高可用的
需要防止兩個namenode同時向共享存儲寫數據導致數據損壞
共享存儲常用的是qjm 包含多個journalnode
共享存儲實現邏輯:
初始化后,active nn會把editlog寫到大多數的journeynode並返回成功,及認定寫入成功
備用的NN定期從Journeynode讀取一批editlog,並應用到內存中的FSImage
NameNode每次寫Editlog都需要傳遞一個epoch給journeynode,jn會對比epoch,如果比自己保存的epoch大或相同,則可以寫,jn更新自己的epoch到最新,否則拒絕操作。在切換時,備用轉換為active時,會把epoc+1,這樣就防止之前的namenode向jn寫日志,即使寫入也會失敗
防止腦裂:
確保只有一個nn能命令dn:
每個nn改變狀態的時候,向dn發送一個自己的狀態和一個新的序列號
dn在運行過程中維護此序號。當failover的時候新的nn在放回dn心跳時,會返回自己的active狀態和一個更大的序列號。dn接收到這個放回時,認為該nn為新的active
如果這時原來的active恢復。返回給dn的心跳信息包含active狀態和原來的序列號,這時dn就會拒絕這個nn命令