1. 程式人生 > >大資料Hadoop中HDFS用法詳細解析

大資料Hadoop中HDFS用法詳細解析

在這裡插入圖片描述
Hadoop–HDFS
Edits和Fsimage機制詳解
在這裡插入圖片描述
概述
fsimage映象檔案包含了整個HDFS檔案系統的所有目錄和檔案的indoe(節點)資訊,比如:/node01/node,會記錄每個節點nodeid,以及節點之間父子路徑。
以及檔名,檔案大小,檔案被切成幾塊,每個資料塊描述資訊、修改時間、訪問時間等;此外還有對目錄的修改時間、訪問許可權控制資訊(目錄所屬使用者,所在組等)等。
另外,edits檔案主要是在NameNode已經啟動情況下對HDFS進行的各種更新操作進行記錄,比如 :hadoop fs -mkdir hadoop fs -delete hadoop fs -put等。
對於每次事務操作,都會用一個TXID來標識,OP_MKDIR OP_DELETE等。
Edits檔案儲存的操作,而fsimage檔案儲存的是執行操作後,變化的狀態。(元資料)
HDFS客戶端執行所有的寫操作都會被記錄到edits檔案中。
關鍵點


1.當執行格式化指令時候,會在指定元資料目錄生成 dfs/name/current/
最開始只有fsimage,沒有edits檔案(因為沒有啟動HDFS)
2.當初次啟動HFDS,會生成edits_inprogress_0000000000000000001,此檔案用於記錄事務(寫操作)
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中指定檔案
@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上
@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上刪除檔案
@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上建立資料夾
@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指定目錄下的檔案
@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 rt=fs.listFiles(new Path("/"), true);
while(rt.hasNext()){System.out.println(rt.next());
}
}
遞迴檢視指定目錄下的檔案
@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 rt=fs.listFiles(new Path("/"), true);while(rt.hasNext()){System.out.println(rt.next());
}
}
重新命名
@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"));
}
獲取檔案的塊資訊
@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.客戶端根據元資料資訊,直接去對應的datanode讀取檔案塊,然後下載到本地(建立本地的輸出流,然後做流的對接)
4.讀完後,關流。
上傳檔案到HDFS

1.Client向namenode發現 Create file請求,目的是獲取HDFS檔案的輸出流。namenode收到請求後,會檢測路徑的合法性和許可權。如果檢測未通過,直接報錯返回。如果通過檢測,namenode會將檔案的切塊資訊(比如檔案被切成幾塊,每個檔案塊的副本存在哪臺datanode上),然後把這些資訊封裝到輸出流裡,返回給客戶端。所以注意:檔案塊的輸出(上傳)是客戶端直接和對應DN互動的,namenode的作用是告訴Client檔案塊要傳送給哪個datanode上。
2.Client通過輸出流,傳送檔案塊(底層會將一個檔案塊打散成一個一個的packet,每個packet的大小=64kb)。這個過程的機制,叫Pipeline(資料流管道機制)這種機制的目的:為了提高網路效率,我們採取了把資料流和控制流分開的措施。在控制流從客戶機到主Chunk、然後冉 到所有二級副本的同時,資料以管道的方式,順序的沿著一個精心選擇的Chunk伺服器鏈推送。我們的目標 是充分利用每臺機器的頻寬,避免網路瓶頸和高延時的連線,最小化推送所有資料的延時。 為了充分利用每臺機器的頻寬,資料沿著一個Chunk伺服器鏈順序的推送,而不是以其它拓撲形式分散 推送(例如,樹型拓撲結構)。線性推送模式下,每臺機器所有的出凵頻寬都用於以最快的速度傳輸資料,而 不是在多個接受者之間分配頻寬。
3.通過資料流管道機制,實現資料的傳送和副本的複製。每臺datanode伺服器收到資料之後,會向上遊反饋ack確認機制。直到第五步的ack傳送給Client之後,再發送下一個packet。依次迴圈,直到所有的資料都複製完畢。此外,在底層傳輸的過程中,會用到全雙工通訊。補充:建議看《Google File System》的3.2節
4.資料上傳完之後,關流。
從HDFS刪除檔案的流程
1、客戶端向namenode發現 刪除檔案指令,比如: xxxxxxxxxx hadoop fs -rm /park01/1.txt
2、namenode收到請求後,會檢查路徑的合法性以及許可權
3、如果檢測通過,會將對應的檔案從元資料中刪除。(注意,此時這個檔案並沒有真正從叢集上被刪除)
4、每臺datanode會定期向namenode傳送心跳,會領取刪除的指令,找到對應的檔案塊,進行檔案塊的刪除。
HDFS的租約機制
HDFS的有個內部機制:不允許客戶端的並行寫。指的是同一時刻內,不允許多個客戶端向一個HDFS上寫資料。所以要實現以上的機制,實現思路就是用互斥鎖,但是如果底層要是用簡單的互斥鎖,可能有與網路問題,造成客戶端不釋放鎖,而造成死鎖。所以Hadoop為了避免這種情況產生,引入租約機制。租約鎖本質上就是一個帶有租期的互斥鎖。
Hadoop的思想來自於Google的論文,
3.1Hadoop 租約鎖對應的類:org.apache.hadoop.hdfs.server.namenode.LeaseManager.Lease還有一個租約鎖管理者:org.apache.hadoop.hdfs.server.namenode.LeaseManager
HDFS特點
1、分散式儲存架構,支援海量資料儲存。(GB、TB、PB級別資料)
2、高容錯性,資料塊擁有多個副本(副本冗餘機制)。副本丟失後,自動恢復。3、低成本部署,Hadoop可構建在廉價的伺服器上。
4、能夠檢測和快速應對硬體故障,通過RPC心跳機制來實現。
5、簡化的一致性模型,這裡指的是使用者在使用HDFS時,所有關於檔案相關的操作,比如檔案切塊、塊的複製、塊的儲存等細節並不需要去關注,所有的工作都已被框架封裝完畢。使用者所需要的做的僅僅是將資料上傳到HDFS。這大大簡化了分散式檔案儲存操作的難度和管理的複雜度。
6、HDFS不能做到低延遲的資料訪問(毫秒級內給出響應)。但是Hadoop的優勢在於它的高吞吐率(吞吐率指的是:單位時間內產生的資料流)。可以說HDFS的設計是犧牲了低延遲的資料訪問,而獲取的是資料的高吞吐率。如果要想獲取低延遲的資料訪問,可以通過Hbase框架來實現。
7、HDFS不許修改資料,所以適用場景是:一次寫入,多次讀取(once-write-many-read)。注意:HDFS允許追加資料,但不允許修改資料。追加和修改的意義是不同的。
8、HDFS不支援併發寫入,一個檔案同一個時間只能有一個寫入者。
9、HDFS不適合儲存海量小檔案,因為會浪費namenode服務節點的記憶體空間
文章來自:https://www.itjmd.com/news/show-4304.html