Hadoop分佈式文件系統
HDFS的設計
HDFS以流式數據訪問模式來存儲超大文件。
流式數據訪問
HDFS的構建思路是這樣的:一次寫入,多次讀取是最高效的。數據集通常是由數據源生成或複製而來,接着長時間在此數據集上進行分析,每次分析都設計數據集的大部分或全部數據。
不適合使用HDFS的場景
1.低時間延遲的訪問
HDFS是爲高數據吞吐量應用優化的,這可能以高延遲作爲代價,對於低延遲訪問需求可以使用HBase
2.大量的小文件
由於namenode將文件系統的元數據存儲在內存中,因此該文件系統所能存儲的文件綜述受限於內存大小
3.多用戶寫入,任意修改
HDFS中可能只有一個writer,而且每次寫入數據都是追加在文件末尾,不支持多用戶寫入,也不支持在文件任意文職的修改。
HDFS的概念
數據塊
默認64MB,HDFS上的文件被劃分爲塊大小的多個分塊,與普通文件系統不同的是,小於一個塊大小的文件不會佔據整個塊空間。
namenode和datanode
HDFS集羣有兩類節點,並以管理者-工作者模式運行,即一個管理者(namenode)和多個工作者(datanode),namenode管理文件系統的命名空間,它維護這個文件系統樹以及整個樹內的文件以及目錄,這些信息以兩種文件形式永久保存在本地磁盤上,命名空間鏡像文件和編輯日誌文件。
Client代表用戶通過namenode和datanode來訪問文件系統,客戶端通過接口提供訪問文件系統的功能。
datanode是文件系統的工作節點,根據需要存儲或檢索數據塊(受client或namenode調度)。
沒有namenode文件系統將無法使用,因此需要對其實現容錯,hadoop提供兩種機制:
1.備份組成文件系統元數據持久狀態的文件。
2.輔助namenode
命令行接口
可以使用命令執行常用的文件系統操作
hadoop fs -help可以查看幫助
Hadoop文件系統
hadoop有一個抽象的文件系統概念,HDFS只是其中一種實現。
Java的抽象類org.apache.hadoop.fs.FileSystem定義了Hadoop的一個文件系統接口,並且該類有幾個具體實現。
見下圖:
Hadoop對文件系統提供了很多接口,一般使用URI選擇不同的文件系統進行交互,比如要想列出本地文件系統根目錄下的文件,可使用如下命令:
hadoop fs -ls file:///
接口
Hadoop是用Java寫的,通過Java API可以調用所有Hadoop文件系統的交互操作。
Java 接口
通過FileSystem API讀取數據
hadoop中使用Path代表一個文件,FileSytem是一個通用的文件系統API,所以第一步是檢索需要使用的文件系統實例,如HDFS。獲取FileSystem實例有兩個方法:
public static FileSystem get(Configuraion conf) throws IOException;
public static FileSystem get(URI uri,Configuraion conf) throws IOException;
Configuration對象封裝了客戶端或服務器的配置。
通過設置配置文件來加載類路徑,第一個方法返回的是默認文件系統(在core-site.xml中設置的),如果沒有設置則返回本地文件系統。
第二個方法返回通過URI和權限指定的文件系統。如果給定URI中沒有猴子腚方案則返回默認文件系統。
有了FileSystem實例後,就可以調用open方法獲取文件輸入流:
public FSDataInputStream open(Path path)throws IOEXception;
public abstract FSDataInputStream open(Path path,int bufferSize)throws IOException;
第一個方法使用默認緩衝區大小4KB
數據流
文件讀取數據流
客戶端通過調用FileSystem對象的open方法來打開需要讀取的文件,對於HDFS而言,這是一個分佈式文件系統對象的一個實例。DistributedFileSystem
通過RPC與namenode通信,以確認文件起始塊的位置。對於每一個塊,namenode返回擁有該塊副本的datanode的地址,datanode根據距離客戶端的
位置遠近進行排序。DistributedFileSystem類給客戶端返回一個FSDataInputStream對象,客戶端使用它讀取數據。FSDataInputStream封裝DFSInputStream
對象,管理datanode和namenode的I/O.接着客戶端通過輸入流的read方法,從距離客戶端最近的datanode處獲取數據,到達塊的末尾後,DFSInputStream
會斷開datanode的連接,並尋找下一個最佳datanode。一旦讀取完成則調用close方法。
寫入文件數據流
客戶端通過調用DistributedFileSystem對象的create()方法創建一個文件,DistributedFileSystem通過RPC通知namenode在namespace中
創建一個新文件,此時該文件還沒有相應的數據塊。namenode會做一系列的檢查確保這個文件還不存在,以及客戶端有權限創建。如果通過,
namenode會創建一個新文件,否則拋出IOException.DistributedFileSystem返回一個FSDataOutputStream對象讓客戶端開始寫入數據。與讀文件類似,
FSDataOutputStream封裝了DFSOuputStream對象,處理與datanode和namenode通信。
寫入數據時,DFSOutputStream將數據分成若干packet,寫入內部隊列。DataStreamer處理內部隊列,它負責請求namenode通過列舉合適的datanode分配新塊
以存儲數據副本。列出的datanode構成一個管線,這裏假設副本爲3個,所以管線包括三個datanode。DataStreamer將packets送至管線中第一個datanode,
該datanode存儲packet並將其送至第二個,以此類推。
DFSOutputStream也維護者一個確認隊列,以等待datanode的確認迴應,當收到所有datanode的確認後,packet纔會被從隊列中移除。
客戶端完成數據寫入後調用close()方法。