《深入理解大数据:大数据处理与编程实践》一一3.3 HDFS文件存储组织与读写...
本節(jié)書摘來自華章計算機《深入理解大數(shù)據(jù):大數(shù)據(jù)處理與編程實踐》一書中的第3章,第3.3節(jié),作者 主 編:黃宜華(南京大學(xué))副主編:苗凱翔(英特爾公司),更多章節(jié)內(nèi)容可以訪問云棲社區(qū)“華章計算機”公眾號查看。
3.3 HDFS文件存儲組織與讀寫
作為一個分布式文件系統(tǒng),HDFS內(nèi)部的數(shù)據(jù)與文件存儲機制、讀寫過程與普通的本地文件系統(tǒng)有較大的差別。下面具體介紹HDFS中數(shù)據(jù)的存儲組織和讀寫過程。
3.3.1 文件數(shù)據(jù)的存儲組織
如前所述,HDFS中最主要的部分就是NameNode和DataNode。NameNode存儲了所有文件元數(shù)據(jù)、文件與數(shù)據(jù)塊的映射關(guān)系,以及文件屬性等核心數(shù)據(jù),DataNode則存儲了具體的數(shù)據(jù)塊。那么,在HDFS中,具體的文件存儲組織結(jié)構(gòu)是怎樣的呢?
1.?NameNode目錄結(jié)構(gòu)
圖3-3是NameNode的目錄結(jié)構(gòu)和內(nèi)容。NameNode借助本地文件系統(tǒng)來保存數(shù)據(jù),保存的文件夾位置由配置選項{dfs.name.dir}決定(未配置此選項,則為hadoop安裝目錄下的/tmp/dfs/name),所以,這里我們以${dfs.name.dir}代表NameNode節(jié)點管理的根目錄。目錄下的文件和子目錄則以${dfs.name.dir}/file和${dfs.name.dir}/subdir的格式表示。
在NameNode的${dfs.name.dir}之下有3個文件夾和1個文件:
1)current目錄:主要包含如下的內(nèi)容和結(jié)構(gòu):
a)文件VERSION:保存了當(dāng)前運行的HDFS版本信息。
b)FsImage:是整個系統(tǒng)的空間鏡像文件。
c)Edit:EditLog編輯日志。
d)Fstime:上一次檢查點的時間。
2)previous.checkpoint目錄:和current內(nèi)容結(jié)構(gòu)一致,不同之處在于,此目錄保存的是上一次檢查點的內(nèi)容。
3)image目錄:舊版本(版本<0.13)的FsImage存儲位置。
4)in_use.lock:NameNode鎖,只有在NameNode有效(啟動并且能和DataNode正常交互)時存在;不滿足上述情況時,該文件不存在。這一文件具有“鎖”的功能,可以防止多個NameNode共享同一目錄(如果一個機器上只有一個NameNode,這也是最常見的情況,那么這個文件基本不需要)。
2.?DataNode目錄結(jié)構(gòu)
圖3-4是DataNode的目錄結(jié)構(gòu)和內(nèi)容。DataNode借助本地文件系統(tǒng)來保存數(shù)據(jù),一般情況下,保存的文件夾位置由配置選項{dfs.data.dir}決定(未配置此選項,則為hadoop安裝目錄下的/tmp/dfs/data)。所以,這里我們以${dfs.data.dir}代表DataNode節(jié)點管理的數(shù)據(jù)目錄的根目錄,目錄下的文件和子目錄則以${dfs.data.dir}/file和${dfs.data.dir}/subdir的格式表示。
圖3-4 HDFS DataNode目錄結(jié)構(gòu)
一般來說,在${dfs.data.dir}之下有4個子目錄和2個文件:
1)current目錄:已經(jīng)成功寫入的數(shù)據(jù)塊,以及一些系統(tǒng)需要的文件。包括以下內(nèi)容:
a)文件VERSION:保存了當(dāng)前運行的HDFS版本信息。
b)Blk_XXXXX和Blk_XXXXX.Meta:分別是數(shù)據(jù)塊和數(shù)據(jù)塊對應(yīng)的元數(shù)據(jù)(比如校驗信息等)。
c)subdirXX:當(dāng)同一目錄下文件數(shù)超過一定限制(比如64)時,會新建一個subdir目錄,保存多出來的數(shù)據(jù)塊和元數(shù)據(jù);這樣可以保證同一目錄下目錄+文件數(shù)不會太多,可以提高搜索效率。
2)tmp目錄和blocksBeingWritten目錄:正在寫入的數(shù)據(jù)塊,tmp目錄保存的是用戶操作引發(fā)的寫入操作對應(yīng)的數(shù)據(jù)塊,blocksBeingWritten目錄是HDFS系統(tǒng)內(nèi)部副本創(chuàng)建時(當(dāng)出現(xiàn)副本錯誤或者數(shù)量不夠等情況時)引發(fā)的寫入操作對應(yīng)的數(shù)據(jù)塊。
3)detach目錄:用于DataNode升級。
4)storage文件:由于舊版本(版本<0.13)的存儲目錄是storage,因此如果在新版本的DataNode中啟動舊版的HDFS,會因為無法打開storage目錄而啟動失敗,這樣可以防止因版本不同帶來的風(fēng)險。
5)in_use.lock文件:DataNode鎖,只有在DataNode有效(啟動并且能和NameNode正常交互)時存在;不滿足上述情況時,該文件不存在。這一文件具有“鎖”的功能,可以防止多個DataNode共享同一目錄(如果一個機器上只有一個DataNode,這也是最常見的情況,那么這個文件基本不需要)。
3.?CheckPointNode目錄結(jié)構(gòu)
圖3-5是CheckPointNode的目錄結(jié)構(gòu)和內(nèi)容。CheckPointNode和舊版本的SecondaryName
Node作用類似,所以目錄結(jié)構(gòu)也十分相近。
圖3-5 HDFS CheckPointNode目錄結(jié)構(gòu)
CheckPointNode借助本地文件系統(tǒng)來保存數(shù)據(jù),一般情況下,保存的文件夾位置由配置選項{dfs.checkpoint.dir}決定(未配置此選項,則為hadoop安裝目錄下的/tmp/dfs/namesecondary)。所以,這里我們以${dfs.checkpoint.dir}代表CheckPointNode節(jié)點管理的數(shù)據(jù)目錄的根目錄,目錄下的文件和子目錄則以${dfs.checkpoint.dir}和file,${dfs.checkpoint.dir}/subdir的格式表示。
CheckPointNode目錄下的文件和NameNode目錄下的同名文件作用基本一致,不同之處在于CheckPointNode保存的是自上一個檢查點之后的臨時鏡像和日志。
3.3.2 數(shù)據(jù)的讀寫過程
數(shù)據(jù)的讀寫過程與數(shù)據(jù)的存儲是緊密相關(guān)的,以下介紹HDFS數(shù)據(jù)的讀寫過程。
1.?數(shù)據(jù)讀取過程
一般的文件讀取操作包括open、read、close等,具體可參見3.5節(jié)的HDFS編程接口介紹。這里介紹一下客戶端連續(xù)調(diào)用open、read、close時,HDFS內(nèi)部的整個執(zhí)行過程。圖3-6可以幫助我們更好地理解這個過程。
圖3-6 HDFS數(shù)據(jù)讀取過程
以下是客戶端讀取數(shù)據(jù)的過程,其中1、3、6步由客戶端發(fā)起:
客戶端首先要獲取FileSystem的一個實例,這里就是HDFS對應(yīng)的實例。
1)首先,客戶端調(diào)用FileSystem實例的open方法,獲得這個文件對應(yīng)的輸入流,在HDFS中就是DFSInputStream。
2)構(gòu)造第1步中的輸入流DFSInputStream時,通過RPC遠程調(diào)用NameNode可以獲得NameNode中此文件對應(yīng)的數(shù)據(jù)塊保存位置,包括這個文件的副本的保存位置(主要是各DataNode的地址)。注意,在輸入流中會按照網(wǎng)絡(luò)拓撲結(jié)構(gòu),根據(jù)與客戶端距離對DataNode進行簡單排序。
3~4)獲得此輸入流之后,客戶端調(diào)用read方法讀取數(shù)據(jù)。輸入流DFSInputStream會根據(jù)前面的排序結(jié)果,選擇最近的DataNode建立連接并讀取數(shù)據(jù)。如果客戶端和其中一個DataNode位于同一機器(比如MapReduce過程中的mapper和reducer),那么就會直接從本地讀取數(shù)據(jù)。
5)如果已到達數(shù)據(jù)塊末端,那么關(guān)閉與這個DataNode的連接,然后重新查找下一個數(shù)據(jù)塊。
不斷執(zhí)行第2~5步直到數(shù)據(jù)全部讀完,然后調(diào)用close。
6)客戶端調(diào)用close,關(guān)閉輸入流DFSInputStream。
另外,如果DFSInputStream和DataNode通信時出現(xiàn)錯誤,或者是數(shù)據(jù)校驗出錯,那么DFSInputStream就會重新選擇DataNode傳輸數(shù)據(jù)。
2.?數(shù)據(jù)寫入過程
一般的文件寫入操作不外乎create、write、close幾種,具體可參見3.5節(jié)的HDFS編程接口介紹。這里介紹一下客戶端連續(xù)調(diào)用create、write、close時,HDFS內(nèi)部的整個執(zhí)行過程,見圖3-7。
以下是客戶端寫入數(shù)據(jù)的過程,其中1、3、6步由客戶端發(fā)起:
客戶端首先要獲取FileSystem的一個實例,這里就是HDFS對應(yīng)的實例。
1~2)客戶端調(diào)用FileSystem實例的create方法,創(chuàng)建文件。NameNode通過一些檢查,比如文件是否存在,客戶端是否擁有創(chuàng)建權(quán)限等;通過檢查之后,在NameNode添加文件信息。注意,因為此時文件沒有數(shù)據(jù),所以NameNode上也沒有文件數(shù)據(jù)塊的信息。創(chuàng)建結(jié)束之后,HDFS會返回一個輸出流DFSDataOutputStream給客戶端。
3)客戶端調(diào)用輸出流DFSDataOutputStream的write方法向HDFS中對應(yīng)的文件寫入數(shù)據(jù)。數(shù)據(jù)首先會被分包,這些分包會寫入一個輸出流的內(nèi)部隊列Data隊列中,接收完數(shù)據(jù)分包,輸出流DFSDataOutputStream會向NameNode申請保存文件和副本數(shù)據(jù)塊的若干個DataNode,這若干個DataNode會形成一個數(shù)據(jù)傳輸管道。
4)DFSDataOutputStream會(根據(jù)網(wǎng)絡(luò)拓撲結(jié)構(gòu)排序)將數(shù)據(jù)傳輸給距離上最短的DataNode,這個DataNode接收到數(shù)據(jù)包之后會傳給下一個DataNode。數(shù)據(jù)在各DataNode之間通過管道流動,而不是全部由輸出流分發(fā),這樣可以減少傳輸開銷。
5)因為各DataNode位于不同機器上,數(shù)據(jù)需要通過網(wǎng)絡(luò)發(fā)送,所以,為了保證所有DataNode的數(shù)據(jù)都是準確的,接收到數(shù)據(jù)的DataNode要向發(fā)送者發(fā)送確認包(ACK Packet)。對于某個數(shù)據(jù)塊,只有當(dāng)DFSDataOutputStream收到了所有DataNode的正確ACK,才能確認傳輸結(jié)束。DFSDataOutputStream內(nèi)部專門維護了一個等待ACK隊列,這一隊列保存已經(jīng)進入管道傳輸數(shù)據(jù)、但是并未被完全確認的數(shù)據(jù)包。
不斷執(zhí)行第3~5步直到數(shù)據(jù)全部寫完,客戶端調(diào)用close關(guān)閉文件。
6)客戶端調(diào)用close方法,DFSDataInputStream繼續(xù)等待直到所有數(shù)據(jù)寫入完畢并被確認,調(diào)用complete方法通知NameNode文件寫入完成。
7)NameNode接收到complete消息之后,等待相應(yīng)數(shù)量的副本寫入完畢后,告知客戶端即可。
在傳輸數(shù)據(jù)的過程中,如果發(fā)現(xiàn)某個DataNode失效(未聯(lián)通,ACK超時),那么HDFS執(zhí)行如下操作:
1)關(guān)閉數(shù)據(jù)傳輸?shù)墓艿馈?br />2)將等待ACK隊列中的數(shù)據(jù)放到Data隊列的頭部。
3)更新正常DataNode中所有數(shù)據(jù)塊的版本;當(dāng)失效的DataNode重啟之后,之前的數(shù)據(jù)塊會因為版本不對而被清除。
4)在傳輸管道中刪除失效的DataNode,重新建立管道并發(fā)送數(shù)據(jù)包。
以上就是HDFS中數(shù)據(jù)讀寫的大致過程。
總結(jié)
以上是生活随笔為你收集整理的《深入理解大数据:大数据处理与编程实践》一一3.3 HDFS文件存储组织与读写...的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 7月份计划-----dream
- 下一篇: 越南黑客组织APT32正对NSA网络武器