前言
本文主要介紹了 HDFS 的體系架構以及其執行流程,並給出了讀寫操作的程式設計例項,希望對 HDFS 有個初步的認識。
簡介
HDFS (Hadoop Distributed File System) 是一個執行在商業 PC 上的分散式檔案系統,其設計思想源自於 Google 2003 年釋出的論文 The Google File System 。HDFS的主要目的是為了解決大規模資料儲存和管理的問題。
體系架構
上圖表明 HDFS 是一個標準的 master/slave 架構,主要由三個部分構成:
- NameNode(master 節點)
- 後設資料(MetaData)的管理,其中後設資料由檔案路徑名、資料塊ID以及儲存位置等資訊構成
- 管理 HDFS 的名字空間。
- SecondaryNameNode
- 定期合併 NameNode 的 edit logs(對檔案系統的改動序列) 到 fsimage(對整個檔案系統的快照),並拷貝修改後的 fsimage 到 NameNode。
- 提供一個 NameNode 的檢查點(切忌認為是 NameNode 的備份),可用於 NameNode 的故障恢復。
- DataNode(slave 節點)
- 提供檔案儲存和進行資料塊操作。
- 週期性的向 NameNode 彙報塊資訊。
這裡對圖中出現的一些概念進行說明:
-
Replication(副本)
為了保證資料的高可用,HDFS 會對寫入的資料進行冗餘儲存,預設情況下會儲存 3 份。
-
Blocks
Block 是最基本的儲存和操作單位(預設情況下為 128M),這裡的 Block 不是指物理 Block ,而是指檔案系統的 Block,其大小一般是物理 Block 的整數倍。
執行流程
讀檔案
讀檔案的過程可以概括為:
- Client 向 NameNode 發起請求獲取檔案資料塊位置資訊
- Client 按照資料塊距 Client 的遠近依次進行連線然後讀取資料
寫檔案
寫檔案的過程可以概括為:
- Client 向 NameNode 發起寫檔案的請求獲得可寫的 DataNode 列表等資訊
- Client 根據 HDFS 設定的分塊大小對檔案進行分塊
- Client 和 NameNode 分配的 DataNode 構成 pipeline 並進行資料寫入
- 寫入完成之後,NameNode 接收來自 DataNode 的訊息進行後設資料的更新
常用命令
檔案操作
-
列出檔案
hdfs dfs -ls <path> 複製程式碼
-
建立目錄
hdfs dfs -mkdir <path> 複製程式碼
-
上傳檔案
hdfs dfs -put <localsrc> <dst> 複製程式碼
-
輸出檔案內容
hdfs dfs -cat <src> 複製程式碼
-
檔案複製到本地
hdfs dfs -get <src> <localdst> 複製程式碼
-
刪除檔案和目錄
hdfs dfs -rm <src> hdfs dfs -rmdir <dir> 複製程式碼
管理
-
檢視統計資訊
hdfs dfsadmin -report 複製程式碼
-
進入和退出安全模式(該模式不允許檔案系統有任何修改)
hdfs dfsadmin -safemode enter hdfs dfsadmin -safemode leave 複製程式碼
程式設計例項
-
IDEA 新建 Maven 專案
勾選相關選項後,點選 next 填入專案相關資訊即可
-
pom.xml 中新增依賴
<dependencies> <dependency> <groupId>org.apache.hadoop</groupId> <artifactId>hadoop-common</artifactId> <version>2.9.2</version> //根據 Hadoop 版本進行選擇 </dependency> <dependency> <groupId>org.apache.hadoop</groupId> <artifactId>hadoop-hdfs</artifactId> <version>2.9.2</version> </dependency> <dependency> <groupId>org.apache.hadoop</groupId> <artifactId>hadoop-client</artifactId> <version>2.9.2</version> </dependency> </dependencies> 複製程式碼
-
讀寫檔案
建立 Sample 類編寫相應的讀寫函式
-
Sample 類
import org.apache.hadoop.conf.Configuration; import org.apache.hadoop.fs.FSDataInputStream; import org.apache.hadoop.fs.FSDataOutputStream; import org.apache.hadoop.fs.FileSystem; import org.apache.hadoop.fs.Path; import java.io.*; /** * @author ikroal */ public class Sample { //預設的 HDFS 地址 private static final String DEFAULT_FS = "hdfs://localhost:9000"; private static final String PATH = DEFAULT_FS + "/tmp/demo.txt"; private static final String DEFAULT_FILE = "demo.txt"; public static void main(String[] args) { Configuration conf = new Configuration(); FileSystem fs = null; conf.set("fs.defaultFS", DEFAULT_FS); //配置 HDFS 地址 try { fs = FileSystem.get(conf); write(fs, DEFAULT_FILE, PATH); read(fs, PATH); } catch (IOException e) { e.printStackTrace(); } finally { try { if (fs != null) { fs.close(); } } catch (IOException e) { e.printStackTrace(); } } } } 複製程式碼
-
write 函式
/** * 進行檔案寫入 * @param inputPath 待寫入檔案路徑 * @param outPath HDFS 的寫入路徑 */ public static void write(FileSystem fileSystem, String inputPath, String outPath) { FSDataOutputStream outputStream = null; FileInputStream inputStream = null; try { outputStream = fileSystem.create(new Path(outPath)); //獲得 HDFS 的寫入流 inputStream = new FileInputStream(inputPath); //讀取本地檔案 int data; while ((data = inputStream.read()) != -1) { //寫入操作 outputStream.write(data); } } catch (IOException e) { e.printStackTrace(); } finally { try { if (outputStream != null) { outputStream.close(); } if (inputStream != null) { inputStream.close(); } } catch (IOException e) { e.printStackTrace(); } } } 複製程式碼
-
read 函式
/** * 進行檔案讀取 * @param path HDFS 上待讀取檔案路徑 */ public static void read(FileSystem fileSystem, String path) { FSDataInputStream inputStream = null; BufferedReader reader = null; try { inputStream = fileSystem.open(new Path(path)); //獲取 HDFS 讀取流 reader = new BufferedReader(new InputStreamReader(inputStream)); String content; while ((content = reader.readLine()) != null) { //讀取並輸出到控制檯 System.out.println(content); } } catch (IOException e) { e.printStackTrace(); } finally { try { if (inputStream != null) { inputStream.close(); } if (reader != null) { reader.close(); } } catch (IOException e) { e.printStackTrace(); } } } 複製程式碼
-
-
在工程資料夾的根目錄下建立計劃上傳的檔案(這裡是 demo.txt),填入 Hello World!
-
啟動 Hadoop 然後執行程式檢視結果
通過 http://localhost:50070/explorer.html#/ 可以檢視寫入結果
控制檯則會輸出上傳檔案的內容