HDFS(Hadoop Distributed File System)作為 Hadoop 生態系統的核心儲存組件,採用主從架構設計,由 NameNode(元數據節點)管理文件系統命名空間與數據塊映射關係,DataNode(數據節點)負責實際數據存儲。理解 HDFS 的文件讀寫流程,對於優化大數據應用性能、排查故障至關重要。本文將結合源碼邏輯與架構圖解,詳細剖析 HDFS 文件讀取與寫入的完整過程。
以下代碼展示了使用 HDFS Java API 讀取文件的標準流程:
Configuration conf = new Configuration();
FileSystem fs = FileSystem.get(conf);
Path file = new Path("demo.txt");
FSDataInputStream inStream = fs.open(file);
String data = inStream.readUTF();
System.out.println(data);
inStream.close();
FileSystem.get(conf) 獲取文件系統實例,隨後調用 open(Path) 方法打開目標文件。FSDataInputStream 給客戶端,客戶端調用 read() 開始讀取數據。DFSInputStream 連接存儲第一個數據塊的最近 DataNode,數據經網絡傳輸至客戶端。DFSInputStream 關閉當前連接,尋找下一個數據塊的最近 DataNode 繼續讀取,直至文件結束。FSDataInputStream.close() 釋放資源。Configuration conf = new Configuration();
FileSystem fs = FileSystem.get(conf);
Path file = new Path("demo.txt");
FSDataOutputStream outStream = fs.create(file);
outStream.writeUTF("Welcome to HDFS Java API!!!");
outStream.close();
create(Path),FileSystem 通過 RPC 請求 NameNode 在命名空間創建新文件。NameNode 校驗文件不存在且客戶端有寫權限後,創建文件元數據條目。DFSOutputStream,客戶端開始寫入數據。DFSOutputStream 將數據切分為數據塊(默認 128MB),放入 DataQueue。DataStreamer 線程從隊列取出數據塊,請求 NameNode 分配存儲節點(默認 3 副本),形成一個「管道」:DN1 → DN2 → DN3。DataStreamer 將數據塊發送給管道首節點 DN1,DN1 再轉發給 DN2,DN2 轉發給 DN3,實現流水線複製。DFSOutputStream 維護 AckQueue 等待管道節點返回寫入成功確認。所有副本寫入成功並收到 ACK 後,才視為該塊寫入完成。close(),刷新剩餘數據塊至管道,等待所有 ACK 返回,最後通知 NameNode 文件寫入完成,更新元數據。DataQueue 頭部。HDFS 通過「元數據與數據分離」、「多副本冗餘」、「流水線寫入」、「客戶端直連 DataNode」等設計,實現了高吞吐、高可靠、可擴展的分布式文件存儲。讀取流程強調「就近讀取」與「自動故障轉移」;寫入流程強調「流水線複製」與「ACK 確認機制」。深入理解這兩大核心流程,有助於開發者優化數據本地性、調整副本策略、排查數據傾斜與節點故障等生產環境問題。