## 媒介
### 前情回溯
假如說上一篇是在論述HDFS最根基的理論常識,這一篇即是HDFS的重要任務流程,和一些較為有用的手段
增補一個疑問,即是當我們 NameNode 掛掉,SecondaryNameNode作為新的NameNode上位時,它的確可以依據fsimage.ckpt把一部門元數據加載到內存,可是假如這時還有一部門操縱日志在edits ne中沒有執行怎麼辦?
這運彩 棒球 讓分時候有一個解決計劃即是應用一個netork fileSystem來解決,例如說集群中有一個辦事器安裝了一個nfs server,而在NameNode上再安裝一個nfs client,此時客戶端向HDFS寫數據時,同時把向edits ne中寫的數據寫一份到nfs server中,SecondaryNamenode就可以通過這個nfs server來獲取此時斷層的數據了
其他好像也沒啥可多說的,讓我們直奔主題吧
以往鏈接
[從零開端的大數據(一) — HDFS的常識概述(上)]
## 一、HDFS的讀流程
之后的內容會環繞下圖開端
![](suser-gold-cdn.xitu.io202411916e4d9327833aa83?=854h=487f=pngs=824)
1.熟悉腳色
簡樸過一下圖里面的腳色,最大塊的是一個client node,也即是說,這個節點上運行著客戶端,假如其實是沒搞清晰哪個是客戶端,那也很簡樸,平時沒事就執行
hadoop fs -ls
這個號召的機械,那即是客戶端了,其他即是NameNode和DataNode,在client node上運行著一個JVM虛擬機,讓HDFS client跑起來
2.程序解析
① HDFS client調用文件體制的open想法
Distributed FileSystem顧名思義是一個分布式文件體制,它會通過RPC的方式長途過程調用**NameNode里的open想法**,這個open想法有什麼作用呢,即是獲取要讀的文件的**file block locations**,也即是文件的block的位置,在上一講我們也已經提到了,一個文件是會劃分成128M一塊的大小差別儲備在各個數據節點的。
同時在執行open想法時,客戶端會產生一個FSData InputStream的一個輸入流對象(客戶端讀數據是從外部讀回來的)
② FSData InputStream讀數據
HDFS client調用FSData InputStream的read想法,同上也是長途過程**調用DataNode的read想法**,此時的讀取次序是由近到遠,即是DataNode和client node的間隔,這里所指的間隔是一種物理間隔,裁定可以參考上一篇詞章中機架的概念。
在聯系上DataNode并勝利讀取后,關閉流就走完了一個正常的流程。
並且增補一下即是,上面Distributed FileSystem所調用的get block locations的想法只會回去部門數據塊,get block locations會分批次地回去block塊的位置信息。讀block塊理論上來說是依次讀,當然也可以通過多線程的方式實現同步讀。
③ 容錯機制
1.假如client從DataNode上讀取block時絡中斷了如何解決?
此時我們會找到block另有的副本(一個block塊有3個副本,上一篇已經說過了),并且通過FSData InputStream進行紀實,以后就不再從中斷的副本上讀了。
2.假如一個DataNode掛掉了怎麼辦?
在上一篇中我們提到了一個HDFS的心跳機制,DataNode會隔一小時向NameNode報告blockReport,例如此刻的場合是,block1的三個副本差別儲備在DataNode1,2,3上,此時DataNode1掛掉了。NameNode得知某個block還剩2個副本,此時攜帶這block的其余兩個副本的DataNode2,3在向NameNode匯報時,NameNode就會對它們中的某一個回去一個指令,把block1復制一份給其他正常的節點。讓block1覆原成原先的3個副本。
3.client如何擔保讀取數據的完整性
由於從DataNode上讀數據是通過絡來讀取的,這說明會存在讀取過來的數據是殘缺的或者是過錯的場合。
DataNode上儲備的不光僅是數據,數據還附帶著一個叫做checkSum檢修和(CRC32算法)的概念,針對于任何大小的數據塊算計CRC32的值都是32位4個字節大小。此時我們的FSData InputStream向DataNode讀數據時,會將與這份數據對應的checkSum也一并讀取過來,此時FSData InputStream再對它讀過來的數據做一個checkSum,把它與讀過來的checkSum做一個對比,假如不一致,就從頭從另有的DataNode上再次讀取。
4.上一個疑問辦妥后任務
FSData InputStream會通知NameNode,這個DataNode上的這個block有疑問了,NameNode收到動靜后就會再通過心跳機制告訴這個DataNode刪除它的block塊,然后再用相似2的做法,讓正常的DataNode去copy一份正常的block數據給別的節點,擔保副本數為3 代碼簡樸示例(可跳過)
try {
String srcFile = “hdfsnode-019000datahdfs01.mp4”;
Configuration conf = ne Configuration();
FileSystem fs = FileSystem.get(URI.create(srcFile),conf);
FSDataInputStream hdfsInStream = fs.open(ne Path(srcFile));
BufferedOutputStream outputStream = ne BufferedOutputStream(ne FileOutputStream(“homenode1hdfs02.mp4”));
IOUtils.copyBytes(hdfsInStream, outputStream, 46, true);
} catch (IOException e) {
e.printStackTrace();
}
## 二、HDFS寫流程
寫流程我們會依照下圖來進行解說,比讀數據加倍復雜一丟丟,腳色根本沒有變更所以就不詳細介紹了
![](suser-gold-cdn.xitu.io2024111216e5bfcaf5528b5d?=864h=587f=pngs=125456)
客戶端向HDFS寫數據的時候是把文件分塊儲備在HDFS的各個節點上,而規定了儲備位置的是NameNode,所以Client node在儲備文件時需求先和NameNode進行聯系讓它進行分發。
程序解析
① 客戶端調用分布式文件體制的create想法
和上面讀的想法相似,但是這一次調用的是Distributed FileSystem的create想法,此時也是通過長途調用NameNode的create想法
此時NameNode會進行的措施
*
1.檢測個人是否正常運行
2.判斷要創造的文件是否存在
3.
client是否有創造文件的權限
4.
對HDFS做狀態的更換需求在edits log寫日志紀實
② 客戶端調用輸出流的rite想法
create想法的回去值是一個OutputStream對象,為什麼是output,由於是由HDFS去往DataNode去寫數據,此時HDFS會調用這個OutputStream的rite想法
不過有個疑問,此時我們還無知道我們的這些block塊要差別寄存于哪些節點上,所以此時FSData OutputStream就要再和NameNode交互一下,長途過程調用**NameNode的addBlock**想法,這個想法**回去的是各個block塊差別需求寫在哪3個DataNode**上面。
此時OutputStream就完整得知了數據和數據該往哪里去寫了
③ 具體的寫流程解析
請看流程4.1,**chunk**是一個512字節大小的數據塊,寫數據的過程中數據是一字節一字節往chunk那里寫的,當寫滿一個chunk后,管帳算一個checkSum,這個checkSum是4個字節大小,算計辦妥后一并放入chunk,所以整一個**chunk大小實在是512字節+4字節=516字節**。
上述程序了結后,一個chunk就會往**package**里面放,package是一個**64kb大小的數據包**,我們知道 64kb = 64 * 1024字節,所以這個package可以放極度多的chunk。
此時一個package滿了之后,會把這個packjage放到一個data queue隊列里面,之后會陸續有源源不停的package傳輸過來,圖中用p1,p2···等表明
這時候開端真正的寫數據過程
1. data queue中的package往數據節點DataNode上傳輸,傳輸的次序依照NameNode的addBlock()想法回去的列表依次傳輸**
(ps:傳輸的類為一個叫做dataStreamer的類,並且實在addBl中華義大利賠率ock想法回去的列表根本是依照離客戶端物理間隔由近到遠的次序的)
2. 往DataNode上傳輸的同時也往確定隊列ack queue上傳輸
3. 針對DataNode中傳輸辦妥的數據做一個checkSum,并與原先打包前的checkSum做一個對照
4. 校驗勝利,就從確定隊列ack queue中刪除該package,不然該package從頭置入data queue重傳
增補:
1.以上邏輯歸屬于FSData OutputStream的邏輯
2.固然本身一個block為128M,而package為64Kb,128M對于絡傳輸過程來說算是對照大,拆分為小包是為了可信傳輸
3.絡中斷時的措施:HDFS會先把整個pine關閉,然后獲取一個已存在的完整的文件的version,發送給NameNode后,由NameNode通過心跳機制對未準確傳輸的數據下達刪除號召
4.假如是某個DataNode不能用,在1中我們也提到過了,通過心跳機制會告訴其余的可用DataNode的此中一個進行copy到一個可用節點上
④ 寫入了結后的舉動
辦妥后通過心跳機制NameNode就可以得知副本已經創造辦妥,再調用addBlock()想法寫之后的文件。
⑤ 流程結算
**1.cl運彩 棒球延賽ient端調用Distributed FileSystem的create,此時是長途調用了NameNode的create,此時NameNode進行4個操縱,檢測個人是否正常,文件是否存在,客戶端的權限和寫日志
2.create的回去值為一個FSData OutputStream對象,此時client調用流的rite想法,和NameNode進行連結,NameNode的addBlock想法回去塊分發的DataNode列表
3.開端寫數據,先寫在chunk,后package,置入data queue,此時兩個操縱,向DataNode傳輸,和放入ack queue,DataNode傳輸了結會檢測checkSum,勝利就刪除ack queue的package,不然放回data queue重傳
4.了結后關閉流,通知NameNode,調用plete想法了結**
#### 簡樸代碼示例(可跳過)
String source=”homenode1hdfs01.mp4″; linux中的文件路徑,demo存在一宿命據
先確保data目次存在
String destination=”hdfsnode-019000datahdfs01.mp4″;HDFS的路徑
InputStream in = null;
try {
in = ne BufferedInputStream(ne FileInputStream(source));
HDFS讀寫的部署文件
Configuration conf = ne Configuration();
FileSystem fs = FileSystem.get(URI.create(destination),conf);
調用Filesystem的create想法回去的是FSDataOutputStream對象
該對象不許可在文件中定位,由於HDFS只許可一個已打開的文件次序寫入或追加
OutputStream out = fs.create(ne Path(destination));
IOUtils.copyBytes(in, out, 46, true);
} catch (FileNotFoundException e) {
System.out.println(“exception”);
e.printStackTrace();
} catch (IOException e) {
System.out.println(“exception1”);
e.printStackTrace();
}
## 3.Hadoop HA高可用
![](suser-gold-cdn.xitu.io2024111216e5c6be60ca70ca?=991h=525f=pngs=235139)
之前已經提到過,元數據是放在NameNode的內存中的,當元數據丟失,造成辦事不能用,這時候就需求時間來覆原。HA就可以讓用戶感知不到這種疑問。
這需求yarn,MapReduce,zookeeper的支持
僅有一個NameNode時,當NameNode掛掉就需求把fsimage讀到內存,然后把edits log所紀實的日志從頭執行一遍,元數據才幹覆原,而這種做法需求大批的時間
所以解決計劃就在于我們要花大批時間來覆原元數據metaData,所以解決的計劃即是讓集群剎那變回可用狀態即可。
通過建置一個stand by的NameNode,并和主NameNode的元數據維持一致,圖中綠色的區域表明一個共享儲備,主NameNode的元數據會傳輸至共享儲備里面,讓stand by的NameNode進行同步。
下面的DataNode會同時往兩個NameNode發送blockReport,由於讀取DataNode的塊信息并不會很快,所認為了擔保在active掛掉的時候,standby能馬上頂上位置,所以要事先讀取塊信息,同時這也是便捷standby來構建它的元數據信息的道路。
active掛掉后讓stand by馬上生效的機制是上面的FailoverControllerActive實現的,簡稱zkfc,它會定時ping主NameNode,假如發明NameNode掛掉,就會告訴我們的zookeeper集群,然后集群的另一個FailoverControllerActive就會告訴stand by。
## 4.Hadoop聯邦
集群中的元數據會保留在NameNode的內存中,而這些元數據每份占用約150字節,對于一個佔有大批文件的集群來說,由於NameNode的metaData被占滿,DataNode就無法寫入了,聯邦就可以協助體制衝破文件數上限
實在即是布置了多個NameNode來共同維護集群,來提升namespace,並且散開了NameNode的拜訪包袱,並且客戶端的讀寫互不陰礙。即是**開拓性,高吞吐和隔離性**。
![](suser-gold-cdn.xitu.io2024111216e5c7b運彩 德國 墨西哥7db12ab04?=868h=521f=pngs=186119)
## 5.HDFS儲備大批小文件
和剛才的聯邦的介紹時的場合一樣,文件數目(每個文件元數據150byte)會陰礙到NameNode的內存
### 計劃1:HAR文件計劃
實在即是通過一個MR步驟把很多小文件合并成一個大文件,需求發動Yarn
# 創造archive文件
hadoop archive -archiveName test.har -p testhar -r 3 th1 th2 outhar # 原文件還存在,需手動刪除
# 察看archive文件
hdfs dfs -ls -R harouthartest.har
# 解壓archive文件
hdfs dfs -cp harouthartest.harth1 hdfsunarchivef
hadoop fs -ls unarchivef # 次序
hadoop distcp harouthartest.harth1 hdfsunarchivef2 # 并行,發動MR
### 計劃2:Sequence File計劃
其核心線上投注 運彩是以文件名為key,文件內容為value結構小文件。
10000個100KB的小文件,可以編寫步驟將這些文件放到一個SequenceFile文件,然后就以數據流的方式處置這些文件,也可以採用MapReduce進行處置。一個SequenceFile是可劃分的,所以MapReduce可將文件切分成塊,每一塊孑立操縱。不像HAR,SequenceFile支持縮減。在多數場合下,以block為單元進行縮減是最好的抉擇,由於一個block涵蓋多條紀實,縮減作用在block之上,比reduce縮減方式(一條一條紀實進行縮減)的縮減比高.把已有的數據轉存為SequenceFile對照慢。比起先寫小文件,再將小文件寫入SequenceFile,一個更好的抉擇是直接將數據寫入一個SequenceFile文件,省去小文件作為中間前言.
此計劃的代碼不是很主要,所以就直接省掉了,其實是想看看長啥樣的可以艾特我
## finally
關于HDFS對照細節的物品在這篇有增補
到此HDFS的內容就差不多了,但願對你會有所協助。之后會繼續往下分享MapReduce,帶你走完整個大數據的流程,感嗜好的友人可以連續注目下,謝謝。