HDFS的基礎(chǔ)總結(jié)及架構(gòu)演進(jìn)
## 前言 截取知識(shí)星球的分享出來,也是對(duì)之前的 HDFS 進(jìn)行一個(gè)補(bǔ)充,順帶讓大家復(fù)習(xí)一下 前面兩篇 HDFS 在這里: [帶你入坑大數(shù)據(jù)(一) --- HDFS基礎(chǔ)概念篇] [帶你入坑大數(shù)據(jù)(二) --- HDFS的讀寫流程和一些重要策略] ## Coutent ### 分散存儲(chǔ),冗余存儲(chǔ) 這兩點(diǎn)我可以展開說明一下,首先我們要清楚,HDFS里面的數(shù)據(jù),分為**真實(shí)數(shù)據(jù)**和**元數(shù)據(jù)**兩種,當(dāng)然這里面元數(shù)據(jù)是在 Namenode 里面的,而真實(shí)數(shù)據(jù)是存儲(chǔ)在 Datanode 里面的。 比如我們現(xiàn)在要存儲(chǔ)一個(gè)大文件,分散存儲(chǔ)的意思就是,會(huì)將這個(gè)文件拆分成一個(gè)個(gè)的數(shù)據(jù)塊block,分別獨(dú)立存放在某個(gè) Datanode 中。那此時(shí)問題就來了,你怎么知道哪個(gè)文件是由哪些數(shù)據(jù)塊組成呢?而且這些數(shù)據(jù)塊又分別存在哪些 Datanode 上呢?
這就是元數(shù)據(jù)所起到的作用。 元數(shù)據(jù)存儲(chǔ)其實(shí)是在內(nèi)存和磁盤都存儲(chǔ)了一份的,存儲(chǔ)在內(nèi)存的考量主要就是提高響應(yīng)速度,而存磁盤是為了保證元數(shù)據(jù)的安全。而這樣導(dǎo)致的問題就是:如何保證內(nèi)存和磁盤的數(shù)據(jù)一致性問題?這塊可以去學(xué)習(xí)一下 Redis 的做法,既保證效率又保證安全。 而且為什么說HDFS不適合存儲(chǔ)小文件,甚至說我們會(huì)有很多小文件的合并機(jī)制,那是因?yàn)樵獢?shù)據(jù)并不是一個(gè)文件一條元數(shù)據(jù),而是每一個(gè)數(shù)據(jù)塊都會(huì)對(duì)應(yīng)有一個(gè)相關(guān)的元數(shù)據(jù)描述,而每個(gè)數(shù)據(jù)塊的元數(shù)據(jù)大小將近150字節(jié),這好比說我們往HDFS存一個(gè)100M的視頻,對(duì)應(yīng)一條150byte的元數(shù)據(jù),如果存100張1M的圖片,就會(huì)有對(duì)應(yīng)100條150byte的元數(shù)據(jù),所以這個(gè)資源的浪費(fèi)是十分可怕的。
而冗余存儲(chǔ)就是我們的block會(huì)有副本機(jī)制,這個(gè)副本的存儲(chǔ)套路是機(jī)架存儲(chǔ)策略 ### 機(jī)架存儲(chǔ)策略 實(shí)際機(jī)房中,會(huì)有機(jī)架,每個(gè)機(jī)架上會(huì)有若干臺(tái)服務(wù)器。一般來說我們會(huì)把一個(gè)block的3個(gè)副本分別按照下述方法進(jìn)行存儲(chǔ):
1. 第一個(gè)副本就存儲(chǔ)在一個(gè)機(jī)架A上 第二個(gè)副本存儲(chǔ)在和這個(gè)block塊不同機(jī)架(比如機(jī)架B)的一個(gè)服務(wù)器上
2. 存儲(chǔ)第2個(gè)副本時(shí)會(huì)優(yōu)先把副本存儲(chǔ)在不同的機(jī)架上,這是為了防止出現(xiàn)一個(gè)機(jī)架斷電的情況,如果副本也存儲(chǔ)在同機(jī)架上的不同服務(wù)器上,這時(shí)候數(shù)據(jù)就可能丟失了。
3. 第三個(gè)副本存儲(chǔ)在機(jī)架B的另外一個(gè)服務(wù)器上(注意副本2,3都存儲(chǔ)在了機(jī)架B) 為什么會(huì)這么選擇,因?yàn)槿绻覀儼迅北?也放在另外一個(gè)機(jī)架C上,副本2和副本3之間的通信就需要副本2通過它的交換機(jī)去聯(lián)系總交換機(jī),然后總交換機(jī)去聯(lián)系機(jī)架C的交換機(jī),需要走的路線非常長,而且機(jī)房中的帶寬資源非常寶貴,如果處于高并發(fā)的情況,很容易就把機(jī)房的帶寬打滿,此時(shí)整一個(gè)集群的響應(yīng)速度會(huì)急劇下降,這時(shí)候服務(wù)就會(huì)出現(xiàn)問題了。 當(dāng)然我們的副本數(shù)也是可以手動(dòng)通過命令增加的,在客戶端訪問量多的時(shí)候,可以適當(dāng)分配一下壓力 $ hadoop fs -setrep -R
4 path + FileName setrep的意思其實(shí)就是set replication,設(shè)置副本數(shù)的縮寫,上面命令就是將副本數(shù)設(shè)置成4份了,后面跟著文件路徑和文件名即可 客戶端的交互全部都是和 Namenode 打交道的,這點(diǎn)和 Kafka 一樣,永遠(yuǎn)都是和 leader 打交道,而不是和 follower。但是你要知道,正常的實(shí)現(xiàn)數(shù)據(jù)的上傳下載的功能確實(shí)是走的 Datanode。
HDFS 的架構(gòu) HDFS的架構(gòu):主從架構(gòu),三大角色
1. Namenode作為集群的老大,掌管HDFS文件系統(tǒng)的元數(shù)據(jù),處理客戶端讀寫請(qǐng)求,HDFS的集群內(nèi)部數(shù)據(jù)安全及負(fù)載均衡等 2. Datanode存儲(chǔ)整個(gè)集群的所有數(shù)據(jù)塊,處理真正的數(shù)據(jù)讀寫
3. SecondaryNamenode嚴(yán)格意義上來說并不屬于namenode的備份節(jié)點(diǎn),它主要起到的作用其實(shí)是替namenode分擔(dān)壓力,降低負(fù)載(元數(shù)據(jù)的編輯日志合并,也就是edits log)之用
心跳機(jī)制 ![](https://user-gold-cdn.xitu.io/2020/7/3/1731456b4df8c774?w=916&h=445&f=png&s=129381) 心跳機(jī)制解決了HDFS集群間的通信問題,還是NameNode命令DataNode執(zhí)行操作的途徑 1. master namenode啟動(dòng)之后,會(huì)開一個(gè)ipc server 2. DataNode啟動(dòng),連接NameNode,每隔3s向NameNode發(fā)送一個(gè)心跳,并攜帶狀態(tài)信息 3. NameNode通過對(duì)這個(gè)心跳的返回值來給DataNode傳達(dá)任務(wù)指令 #### 心跳機(jī)制的作用: 1.NameNode 全權(quán)管理數(shù)據(jù)塊的復(fù)制,它周期性從集群中的每個(gè) DataNode 接收心跳信號(hào)和 block 狀態(tài)報(bào)告,接收到心跳信號(hào)意味著該 DataNode 節(jié)點(diǎn)工作正常,塊狀態(tài)報(bào)告包含了該 DataNode 上所有數(shù)據(jù)塊的列表 2.DataNode啟動(dòng)時(shí)向 NameNode 注冊(cè),通過后周期性地向 NameNode 上報(bào) block 報(bào)告,每3秒向 NameNode 發(fā)送一次心跳,NameNode 返回對(duì)該 DataNode 的指令,如將數(shù)據(jù)塊復(fù)制到另一臺(tái)機(jī)器,或刪除某個(gè)數(shù)據(jù)塊等···而當(dāng)某一個(gè) DataNode 超過10min還沒向 NameNode 發(fā)送心跳,此時(shí) NameNode 就會(huì)判定該 DataNode 不可用,此時(shí)客戶端的讀寫操作就不會(huì)再傳達(dá)到該 DataNode 上
安全模式 3.hadoop 集群剛開始啟動(dòng)時(shí)會(huì)進(jìn)入安全模式(99.99%),就用到了心跳機(jī)制,其實(shí)就是在集群剛啟動(dòng)的時(shí)候,每一個(gè) DataNode 都會(huì)向 NameNode 發(fā)送 block 報(bào)告,NameNode 會(huì)統(tǒng)計(jì)它們上報(bào)的總block數(shù),除以一開始知道的總個(gè)數(shù)total,當(dāng) block/total < 99.99% 時(shí),會(huì)觸發(fā)安全模式,安全模式下客戶端就沒法向HDFS寫數(shù)據(jù),只能進(jìn)行讀數(shù)據(jù)。 而且補(bǔ)充一點(diǎn),Namenode感知Datanode掉線死亡時(shí)間的計(jì)算公式為: timeout = 2 * heartbeat.recheck.interval + 10 * dfs.heartbeat.interval HDFS默認(rèn)超時(shí)時(shí)間為630秒,因?yàn)槟J(rèn)的 heartbeat.recheck.interval 為5分鐘,而 dfs.heartbeat.interval 默認(rèn)為3秒,而這兩個(gè)參數(shù)理解起來也很簡(jiǎn)單,一個(gè)是重新檢查的時(shí)間間隔,而另一個(gè)是每n秒發(fā)送一次心跳的參數(shù),等待10次,不行拉倒。
安全模式的補(bǔ)充 安全模式不僅僅是集群剛啟動(dòng)時(shí)等所有的Datanode匯報(bào)這一種情況會(huì)進(jìn)入安全模式的,還有就是HDFS數(shù)據(jù)塊丟失達(dá)到一個(gè)比例的時(shí)候,也會(huì)自動(dòng)進(jìn)入,當(dāng)然我們也可以手動(dòng)去進(jìn)入安全模式。這個(gè)比例默認(rèn)是0.1%,1000個(gè)塊丟1個(gè)已經(jīng)很嚴(yán)重的事件了。 可以通過 start-balancer.sh 來讓HDFS做負(fù)載均衡,可是要注意,這個(gè)命令是存在一定的問題的,這和Java的垃圾回收機(jī)制中的 System.gc() 是一樣的。
我告訴你,現(xiàn)在要去進(jìn)行垃圾回收了,可是 JVM 壓根就不理咱們,為啥呢?它只會(huì)在自己有空,合適的時(shí)間去做垃圾回收,而 start-balancer.sh 就也是一樣的套路,利用剩余的帶寬去做這個(gè)事情。 而這個(gè)操作也有一定的標(biāo)準(zhǔn),根據(jù)一個(gè)數(shù)值n規(guī)定。每一個(gè)節(jié)點(diǎn)都計(jì)算出一個(gè)磁盤的占用量,占用量最大-占用量最小 = 這個(gè)標(biāo)準(zhǔn)數(shù)值n即可。默認(rèn)是10%,這樣就很好理解了吧。而且這個(gè)負(fù)載均衡的操作是一定不能影響到客戶端的讀寫業(yè)務(wù)的,所以HDFS默認(rèn)會(huì)不允許balance操作占用太多的帶寬。但是我們可以進(jìn)行手動(dòng)調(diào)整 hdfs dfs admin -setBalancerBandwidth newbandwidth newbandwidth 的默認(rèn)單位是字節(jié),所以這個(gè)東西自己根據(jù)需求調(diào)整即可。默認(rèn)是1M每秒的。
HDFS的缺陷及演進(jìn) Hadoop1 版本剛出來的時(shí)候是為了解決兩個(gè)問題:一個(gè)是海量數(shù)據(jù)如何存儲(chǔ)的問題,一個(gè)是海量數(shù)據(jù)如何計(jì)算的問題 Namenode的工作:
1. 管理集群元數(shù)據(jù)信息(文件目錄樹): 可以簡(jiǎn)單理解為,一個(gè)文件被分為了幾個(gè)block塊,而這些block塊又分別存儲(chǔ)在了哪些位置。
2. Namenode為了快速響應(yīng)用戶的操作請(qǐng)求,所以將元數(shù)據(jù)加載到了內(nèi)存里面 Datanode的工作:
1. 存儲(chǔ)數(shù)據(jù),把上傳的數(shù)據(jù)劃分為固定大小的文件塊,hadoop1默認(rèn)64,之后是128M 2. 為了保證數(shù)據(jù)安全,每個(gè)文件塊默認(rèn)都有三個(gè)副本,這里的三個(gè)副本其實(shí)是總共3個(gè)的意思,而不是一份原始3個(gè)備份總數(shù)為4 #### HDFS1的架構(gòu)缺陷 1. 單點(diǎn)故障問題:Namenode掛掉集群就廢了
2. 內(nèi)存受限問題:就是Namenode的元數(shù)據(jù)信息撐爆了內(nèi)存的情況下,整個(gè)集群就癱瘓了 #### QJM方案解決單點(diǎn)故障問題 其實(shí)本身還存在一個(gè)多個(gè)Namenode共用一個(gè)共享目錄的解決方式,但是這樣也會(huì)存在共享目錄出現(xiàn)問題的情況,所以就無法滿足我們的要求 QJM方案如下:我們單獨(dú)建立一個(gè)JournalNode集群,然后由它們來解決單點(diǎn)故障的問題,JournalNode之間數(shù)據(jù)是一致的,我們的主Namenode,也就是active Namenode對(duì)元數(shù)據(jù)進(jìn)行修改的時(shí)候,會(huì)對(duì)JournalNode進(jìn)行寫入操作,然后再由Standby Namenode去進(jìn)行同步以達(dá)到主從Namenode的數(shù)據(jù)一致。
![](https://user-gold-cdn.xitu.io/2020/7/3/173143a1a758a9c8?w=780&h=516&f=png&s=52215) 但是現(xiàn)在還是存在一個(gè)問題,就是我們需要手動(dòng)將standby切換成active,所以此時(shí)我們就引入了Zookeeper來解決這個(gè)問題,其實(shí)存在一些企業(yè)會(huì)有直接不使用JournalNode而直接使用Zookeeper來代替的方案,因?yàn)镴ournalNode的任務(wù)就是保證這些節(jié)點(diǎn)的數(shù)據(jù)一致而已,這個(gè)特點(diǎn)通過Zookeeper的原子廣播協(xié)議是完全可以做到的。
[](https://user-gold-cdn.xitu.io/2020/7/3/1731463f9eded92e?w=787&h=678&f=png&s=69453) 此時(shí)在Zookeeper中創(chuàng)建一個(gè)鎖的目錄,然后NameNode啟動(dòng)的時(shí)候都會(huì)過去搶占鎖,兩個(gè)NameNode誰先搶到,誰就是active狀態(tài)。而且每一個(gè)NameNode上還有一個(gè)ZKFC的服務(wù),持續(xù)監(jiān)聽NameNode的健康狀態(tài),如果active NameNode出現(xiàn)問題,ZKFC將會(huì)報(bào)告給Zookeeper,然后Zookeeper會(huì)將鎖分配給standby的NameNode上。使其自動(dòng)切換為active狀態(tài)。此時(shí)就是HDFS2的架構(gòu)了。 #### JournalNode推薦 因?yàn)槠鋵?shí)JournalNode的任務(wù)并不重,所以不需要太過于龐大的集群 200個(gè)節(jié)點(diǎn)以下 ---> 3個(gè) 200~2000個(gè)節(jié)點(diǎn) ---> 5個(gè) #### 聯(lián)邦解決內(nèi)存受限問題 ![](https://user-gold-cdn.xitu.io/2020/7/3/17314652201b40b1?w=993&h=725&f=png&s=88902) 如上圖,就是等于一個(gè)橫向擴(kuò)展的方式,既然一個(gè)Namenode會(huì)撐爆,那么多個(gè)Namenode,負(fù)責(zé)存儲(chǔ)不同的元數(shù)據(jù)信息即可。
這就好比我們的C,D,E,F盤,C盤是存放系統(tǒng)的一些東西,D盤拿來裝軟件,E盤拿來放電影是一個(gè)道理。而且聯(lián)邦機(jī)制,HDFS 自動(dòng)路由。用戶不用關(guān)心是具體是哪個(gè) namenode 去進(jìn)行存儲(chǔ)了 此時(shí)作一個(gè)小總結(jié),active+standby 的Namenode形成一組,目的是做高可用,防止單點(diǎn)故障。而多組active+standby形成聯(lián)邦,目的是解決單組內(nèi)存不夠的問題。 #### HDFS如何管理元數(shù)據(jù) 還記得我們搭建集群的時(shí)候,在啟動(dòng)集群之前需要做一步“格式化Namenode”的操作嗎?這一步的目的就是在磁盤上生成fsimage,也就是我們的元數(shù)據(jù)目錄信息。此時(shí)再把這個(gè)元數(shù)據(jù)加載到內(nèi)存。
[](https://user-gold-cdn.xitu.io/2020/7/3/1731467460c189a8?w=772&h=598&f=png&s=54508) 如下圖,此時(shí)假如客戶端要上傳文件,它就會(huì)和內(nèi)存中的fsimage進(jìn)行交互,增加一條元數(shù)據(jù)信息,這個(gè)操作就會(huì)寫入到一份 edit log 中去,顧名思義就是編輯日志。而磁盤中的fsimage此時(shí)還是最一開始的那份,不像內(nèi)存中的fsimage是隨時(shí)在變化的。此時(shí) 內(nèi)存fsimage = 磁盤fsimage + edit log 此時(shí)如果我停止了服務(wù),內(nèi)存中的fsimage被銷毀,此時(shí)我只需要將edit log中的記錄回放,刷寫成新的一份fsimage,此時(shí)集群再次啟動(dòng),再加載到內(nèi)存中,就恢復(fù)成為我們停止服務(wù)前的狀態(tài)了。 ![](https://user-gold-cdn.xitu.io/2020/7/3/1731468364b03136?w=1240&h=687&f=png&s=129668) 此時(shí)引入SecondaryNamenode,它的作用就是提高Namenode的恢復(fù)速度,大致對(duì)操作步驟進(jìn)行一個(gè)闡述:
1. SecondaryNameNode 會(huì)通過http get方式把edits log和fsimage的信息拉取過來
2. 在SecondaryNameNode中把edits log和fsimage做一個(gè)合并,產(chǎn)生一個(gè)新的文件叫做 fsimage.ckpt
3. 在SecondaryNameNode中合并完成之后,再回傳給NameNode里面
4. 這時(shí)大概率會(huì)有客戶端還在對(duì)NameNode進(jìn)行讀寫操作,也會(huì)產(chǎn)生新的日志,此時(shí)按照先前未引入SNN的套路繼續(xù)即可。 在HA方案中這個(gè)行為可以交給standby去完成。
雙緩沖機(jī)制 Namenode里面的元數(shù)據(jù)是以兩種狀態(tài)進(jìn)行存儲(chǔ)的: 第一狀態(tài)即是存儲(chǔ)在內(nèi)存里面,也就是剛剛所提到的目錄樹,它就是一個(gè)list,在內(nèi)存里面更新元數(shù)據(jù)速度是很快的。但是如果僅僅只在內(nèi)存里存放元數(shù)據(jù),數(shù)據(jù)是不太安全的。
所以我們?cè)诖疟P上也會(huì)存儲(chǔ)一份元數(shù)據(jù),可是此時(shí)問題就出現(xiàn)了,我們需要把數(shù)據(jù)寫進(jìn)磁盤,這個(gè)性能肯定是不太好的呀。可NameNode作為整個(gè)集群的老大,在hadoop上進(jìn)行hive,HBASE,spark,flink等計(jì)算,這些數(shù)據(jù)都會(huì)不停給NameNode施壓寫元數(shù)據(jù),一天下來一億條元數(shù)據(jù)都是可能的,所以NameNode的設(shè)計(jì)肯定是要支持超高并發(fā)的,可是寫磁盤這操作是非常非常慢的,一秒幾十或者最多幾百都已經(jīng)封頂了,那現(xiàn)在咋辦? ![](https://user-gold-cdn.xitu.io/2020/7/3/1731469118400032?w=809&h=304&f=png&s=87341) 首先我們的客戶端(這里指的是hive,hbase,spark···都沒關(guān)系)所產(chǎn)生的數(shù)據(jù)將會(huì)走兩個(gè)流程,第一個(gè)流程會(huì)向內(nèi)存處寫入數(shù)據(jù),這個(gè)過程非???,也不難理解 ![](https://user-gold-cdn.xitu.io/2020/7/3/173146a8a8b07c92?w=812&h=395&f=png&s=108401) 這時(shí)候肯定就不能直接寫內(nèi)存了,畢竟我們是明知道這東西非常慢的,真的要等它一條條數(shù)據(jù)寫到磁盤,那特么我們都可以雙手離開鼠標(biāo)鍵盤下班走人了。
那NameNode一個(gè)東西不行就整個(gè)集群都不行了,那現(xiàn)在我們?cè)撊绾谓鉀Q? ![](https://user-gold-cdn.xitu.io/2020/7/3/173146ae924df870?w=887&h=629&f=png&s=247862) 雙緩沖機(jī)制就是指我們將會(huì)開辟兩份一模一樣的內(nèi)存空間,一個(gè)為bufCurrent,產(chǎn)生的數(shù)據(jù)會(huì)直接寫入到這個(gè)bufCurrent,而另一個(gè)叫bufReady,在bufCurrent數(shù)據(jù)寫入(其實(shí)這里可能不止一條數(shù)據(jù),等下會(huì)說明)后,兩片內(nèi)存就會(huì)exchange(交換)。
然后之前的bufCurrent就負(fù)責(zé)往磁盤上寫入數(shù)據(jù),之前的bufReady就繼續(xù)接收客戶端寫入的數(shù)據(jù)。其實(shí)就是將向磁盤寫數(shù)據(jù)的任務(wù)交給了后臺(tái)去做。這個(gè)做法,在JUC里面也有用到 而且在此基礎(chǔ)上,hadoop會(huì)給每一個(gè)元數(shù)據(jù)信息的修改賦予一個(gè)事務(wù)ID號(hào),保證操作都是有序的。這也是出于數(shù)據(jù)的安全考慮。這樣整個(gè)系統(tǒng)要求的內(nèi)存會(huì)非常大,所以這關(guān)乎一個(gè)hadoop的優(yōu)化問題,在之后將會(huì)提及。
聲明:免責(zé)聲明:本文內(nèi)容由互聯(lián)網(wǎng)用戶自發(fā)貢獻(xiàn)自行上傳,本網(wǎng)站不擁有所有權(quán),也不承認(rèn)相關(guān)法律責(zé)任。如果您發(fā)現(xiàn)本社區(qū)中有涉嫌抄襲的內(nèi)容,請(qǐng)發(fā)
送郵件至:operations@xinnet.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),本站將立刻刪除涉嫌侵權(quán)內(nèi)容。本站原創(chuàng)內(nèi)容未經(jīng)允許不得轉(zhuǎn)載,或轉(zhuǎn)載時(shí)
需注明出處:新網(wǎng)idc知識(shí)百科