Hadoop--HDFS

Hadoop--HDFS

Edits和Fsimage機制詳解

概述

fsimage鏡像文件包含了整個HDFS文件系統的全部目錄和文件的indoe(節點)信息,好比:/node01/node,會記錄每一個節點nodeid,以及節點之間父子路徑。html

以及文件名,文件大小,文件被切成幾塊,每一個數據塊描述信息、修改時間、訪問時間等;此外還有對目錄的修改時間、訪問權限控制信息(目錄所屬用戶,所在組等)等。java

另外,edits文件主要是在NameNode已經啓動狀況下對HDFS進行的各類更新操做進行記錄,好比 :hadoop fs -mkdir hadoop fs -delete hadoop fs -put等。node

對於每次事務操做,都會用一個TXID來標識,OP_MKDIR OP_DELETE等。git

Edits文件存儲的操做,而fsimage文件存儲的是執行操做後,變化的狀態。(元數據)github

HDFS客戶端執行全部的寫操做都會被記錄到edits文件中。web

關鍵點

1.當執行格式化指令時候,會在指定元數據目錄生成 dfs/name/current/shell

最開始只有fsimage,沒有edits文件(由於沒有啓動HDFS)apache

2.當初次啓動HFDS,會生成edits_inprogress_0000000000000000001,此文件用於記錄事務(寫操做)windows

3.HDFS對於每次寫操做,都會用一個事務ID(TXID)來記錄,TXID是遞增的。服務器

4.edits_0000000000000000003-0000000000000000007,數字表示的合併後起始的事務id和終止事務id

5.seen_txid 存儲的當前的事務id,和edits_inprogress最後的數字一致

6.datanode存儲塊的目錄路徑:/tmp/dfs/data/current/BP-859711469-192.168.150.137-1535216211704/current/finalized/subdir0/subdir0

7.finalized此目錄存儲的已經存儲完畢的數據塊,rbw目錄存的是正在寫但還未寫完的數據塊

查看Edits文件和Fsimage文件

hdfs oev -i edits_0000000000000000001-0000000000000000003 -o edits.xml

hdfs oiv -i fsimage_0000000000000000012 -o fsimage.xml -p XML

HDFS API操做

1.建立java工程

2.導入hadoop依賴jar包

鏈接namenode以及讀取hdfs中指定文件
 
 
 
x
 
 
 
 
@Test
public void testConnectNamenode() throws Exception{
Configuration conf=new Configuration();
FileSystem fs=FileSystem.get(new URI("hdfs://192.168.234.211:9000"), conf);
InputStream in=fs.open(new Path("/park/1.txt"));
OutputStream out=new FileOutputStream("1.txt");
IOUtils.copyBytes(in, out, conf);
}
 
上傳文件到hdfs上
 
 
 
xxxxxxxxxx
 
 
 
 
@Test
public void testPut() throws Exception{
Configuration conf=new Configuration();
conf.set("dfs.replication","1");
FileSystem fs=FileSystem.get(new URI("hdfs://192.168.234.21:9000"),conf,"root");
ByteArrayInputStream in=new ByteArrayInputStream("hello hdfs".getBytes());
OutputStream out=fs.create(new Path("/park/2.txt"));
IOUtils.copyBytes(in, out, conf);
}
 
從hdfs上刪除文件
 
 
 
xxxxxxxxxx
 
 
 
 
@Test
public void testDelete()throws Exception{
Configuration conf=new Configuration();
FileSystem fs=FileSystem.get(new URI("hdfs://192.168.234.21:9000"),conf,"root");
//true表示不管目錄是否爲空,都刪除掉。能夠刪除指定的文件
fs.delete(new Path("/park01"),true);
//false表示只能刪除不爲空的目錄。
fs.delete(new Path("/park01"),false);
fs.close();
}
 
在hdfs上建立文件夾
 
 
 
xxxxxxxxxx
 
 
 
 
@Test
public void testMkdir()throws Exception{
Configuration conf=new Configuration();
FileSystem fs=FileSystem.get(new URI("hdfs://192.168.234.211:9000"),conf,"root");
fs.mkdirs(new Path("/park02"));
}
 
查詢hdfs指定目錄下的文件
 
 
 
xxxxxxxxxx
 
 
 
 
@Test
public void testLs()throws Exception{
Configuration conf=new Configuration();
FileSystem fs=FileSystem.get(new URI("hdfs://192.168.234.214:9000"),conf,"root");
RemoteIterator<LocatedFileStatus> rt=fs.listFiles(new Path("/"), true);
while(rt.hasNext()){
System.out.println(rt.next());
}
}
 
遞歸查看指定目錄下的文件
 
 
 
xxxxxxxxxx
 
 
 
 
@Test
public void testLs()throws Exception{
Configuration conf=new Configuration();
FileSystem fs=FileSystem.get(new URI("hdfs://192.168.234.214:9000"),conf,"root");
RemoteIterator<LocatedFileStatus> rt=fs.listFiles(new Path("/"), true);
while(rt.hasNext()){
System.out.println(rt.next());
}
}
 

 

重命名
 
 
 
xxxxxxxxxx
 
 
 
 
@Test
public void testCreateNewFile() throws Exception{
Configuration conf=new Configuration();
FileSystem fs=FileSystem.get(new URI("hdfs://192.168.234.176:9000"),conf,"root");
fs.rename(new Path("/park"), new Path("/park01"));
 
        
}
 

 

獲取文件的塊信息
 
 
 
xxxxxxxxxx
 
 
 
 
@Test
public void testCopyFromLoaclFileSystem() throws Exception{
Configuration conf=new Configuration();
FileSystem fs=FileSystem.get(new URI("hdfs://192.168.234.176:9000"),conf,"root");
BlockLocation[] data=fs.getFileBlockLocations(new Path("/park01/1.txt"),0,Integer.MaxValue);
for(BlockLocation bl:data){
System.out.println(bl);
}
}
 

從HDFS下載文件過程

1.Client向namenode發起 Open file 請求。目的是獲取指定文件的輸入流。

namenode收到請求以後,會檢查路徑的合法性,此外,仍是檢查客戶端的操做權限。若是檢測未經過,則直接報錯返回。後續過程不會發生。

2.Client也會向namenode發起:Getblockloaction請求,獲取指定文件的元數據信息。若是第一步的檢測經過,namenode會將元數據信息封裝到輸入流裏,返回給客戶端。

3.4 客戶端根據元數據信息,直接去對應的datanode讀取文件塊,而後下載到本地(建立本地的輸出流,而後作流的對接)

5.讀完後,關流。

上傳文件到HDFS

1.Client向namenode發現 Create file請求,目的是獲取HDFS文件的輸出流。namenode收到請求後,會檢測路徑的合法性和權限。若是檢測未經過,直接報錯返回。

若是經過檢測,namenode會將文件的切塊信息(好比文件被切成幾塊,每一個文件塊的副本存在哪臺datanode上),而後把這些信息封裝到輸出流裏,返回給客戶端。

因此注意:文件塊的輸出(上傳)是客戶端直接和對應DN交互的,namenode的做用是告訴Client文件塊要發送給哪一個datanode上。

 

2.Client經過輸出流,發送文件塊(底層會將一個文件塊打散成一個一個的packet,每一個packet的大小=64kb)。這個過程的機制,叫Pipeline(數據流管道機制)

這種機制的目的:

爲了提升網絡效率,咱們採起了把數據流和控制流分開的措施。在控制流從客戶機到主Chunk、而後冉 到全部二級副本的同時,數據以管道的方式,順序的沿着一個精心選擇的Chunk服務器鏈推送。咱們的目標 是充分利用每臺機器的帶寬,避免網絡瓶頸和高延時的鏈接,最小化推送全部數據的延時。 爲了充分利用每臺機器的帶寬,數據沿着一個Chunk服務器鏈順序的推送,而不是以其它拓撲形式分散 推送(例如,樹型拓撲結構)。線性推送模式下,每臺機器全部的出凵帶寬都用於以最快的速度傳輸數據,而 不是在多個接受者之間分配帶寬。

3.4.5 。經過數據流管道機制,實現數據的發送和副本的複製。每臺datanode服務器收到數據以後,會向上遊反饋ack確認機制。直到第五步的ack發送給Client以後,再發送下一個packet。依次循環,直到全部的數據都複製完畢。此外,在底層傳輸的過程當中,會用到全雙工通訊。

補充:建議看《Google File System》的3.2節

6.數據上傳完以後,關流。

從HDFS刪除文件的流程

一、客戶端向namenode發現 刪除文件指令,好比:

 
 
 
xxxxxxxxxx
 
 
 
 
hadoop fs  -rm /park01/1.txt
 

二、namenode收到請求後,會檢查路徑的合法性以及權限

三、若是檢測經過,會將對應的文件從元數據中刪除。(注意,此時這個文件並無真正從集羣上被刪除)

四、每臺datanode會按期向namenode發送心跳,會領取刪除的指令,找到對應的文件塊,進行文件塊的刪除。

HDFS的租約機制

HDFS的有個內部機制:不容許客戶端的並行寫。指的是同一時刻內,不容許多個客戶端向一個HDFS上寫數據。

因此要實現以上的機制,實現思路就是用互斥鎖,可是若是底層要是用簡單的互斥鎖,可能有與網絡問題,形成客戶端不釋放鎖,而形成死鎖。因此Hadoop爲了不這種狀況產生,引入租約機制。

租約鎖本質上就是一個帶有租期的互斥鎖。

Hadoop的思想來自於Google的論文,3.1

Hadoop 租約鎖對應的類:org.apache.hadoop.hdfs.server.namenode.LeaseManager.Lease

還有一個租約鎖管理者:

org.apache.hadoop.hdfs.server.namenode.LeaseManager

HDFS特色

一、分佈式存儲架構,支持海量數據存儲。(GB、TB、PB級別數據)

二、高容錯性,數據塊擁有多個副本(副本冗餘機制)。副本丟失後,自動恢復。

三、低成本部署,Hadoop可構建在廉價的服務器上。

四、可以檢測和快速應對硬件故障,經過RPC心跳機制來實現。

五、簡化的一致性模型,這裏指的是用戶在使用HDFS時,全部關於文件相關的操做,好比文件切塊、塊的複製、塊的存儲等細節並不須要去關注,全部的工做都已被框架封裝完畢。用戶所須要的作的僅僅是將數據上傳到HDFS。這大大簡化了分佈式文件存儲操做的難度和管理的複雜度。

六、HDFS不能作到低延遲的數據訪問(毫秒級內給出響應)。可是Hadoop的優點在於它的高吞吐率(吞吐率指的是:單位時間內產生的數據流)。能夠說HDFS的設計是犧牲了低延遲的數據訪問,而獲取的是數據的高吞吐率。若是要想獲取低延遲的數據訪問,能夠經過Hbase框架來實現。

七、HDFS不準修改數據,因此適用場景是:一次寫入,屢次讀取(once-write-many-read)。注意:HDFS容許追加數據,但不容許修改數據。追加和修改的意義是不一樣的。

八、HDFS不支持併發寫入,一個文件同一個時間只能有一個寫入者。

九、HDFS不適合存儲海量小文件,由於會浪費namenode服務節點的內存空間

相關文章
相關標籤/搜索