Hadoop学习笔记—2.不怕故障的海量存储:HDFS基础入门
一.HDFS出現的背景
隨著社會的進步,需要處理數據量越來越多,在一個操作系統管轄的范圍存不下了,那么就分配到更多的操作系統管理的磁盤中,但是卻不方便管理和維護—>因此,迫切需要一種系統來管理多臺機器上的文件,于是就產生了分布式文件管理系統,英文名成為DFS(Distributed File System)。
那么,什么是分布式文件系統?簡而言之,就是一種允許文件通過網絡在多臺主機上分享的文件系統,可以讓多個機器上的多個用戶分享文件和存儲空間。它最大的特點是“通透性”,DFS讓實際上是通過網絡來訪問文件的動作,由用戶和程序看來,就像是訪問本地的磁盤一般(In other words,使用DFS訪問數據,你感覺不到是訪問遠程不同機器上的數據)。
圖1.一個典型的DFS示例
二.深入了解HDFS原理
作為Hadoop的核心技術之一,HDFS(Hadoop Distributed File System,Hadoop分布式文件系統)是分布式計算中數據存儲管理的基礎。它所具有的高容錯、高可靠、高可擴展性、高吞吐率等特性為海量數據提供了不怕故障的存儲,也為超大規模數據集(Large Data Set)的應用處理帶來了很多便利。
圖2.Hadoop HDFS的LOGO
提到HDFS,不得不說Google的GFS。正是Google發表了關于GFS的論文,才有了HDFS這個關于GFS的開源實現。
2.1 設計前提與目標
(1)硬件錯誤是常態而不是異常;(最核心的設計目標—>HDFS被設計為運行在眾多的普通硬件上,所以硬件故障是很正常的。因此,錯誤檢測并快速恢復是HDFS最核心的設計目標)
(2)流式數據訪問;(HDFS更關注數據訪問的高吞吐量)
(3)大規模數據集;(HDFS的典型文件大小大多都在GB甚至TB級別)
(4)簡單一致性模型;(一次寫入,多次讀取的訪問模式)
(5)移動計算比移動數據更為劃算;(對于大文件來說,移動計算比移動數據的代價要低)
2.2 HDFS的體系結構
HDFS是一個主/從(Master/Slave)式的結構,如下圖所示。
圖3.HDFS的基本架構
從最終用戶的角度來看,它就像傳統的文件系統一樣,可以通過目錄路徑對文件執行CRUD(增刪查改)操作。但由于分布式存儲的性質,HDFS擁有一個NameNode和一些DataNodes。NameNode管理文件系統的元數據,DataNode存儲實際的數據。客戶端通過同NameNode和DataNode的交互訪問文件系統→客戶端聯系NameNode以獲取文件的元數據,而真正的I/O操作是直接和DataNode進行交互的。
下面我們再來看看HDFS的讀操作和寫操作的流程:
①讀操作
圖4.HDFS的讀操作
客戶端要訪問一個文件,首先,客戶端從NameNode中獲得組成該文件數據塊位置列表,即知道數據塊被存儲在哪幾個DataNode上;然后,客戶端直接從DataNode上讀取文件數據。在此過程中,NameNode不參與文件的傳輸。
②寫操作
圖5.HDFS的寫操作
客戶端首先需要向NameNode發起寫請求,NameNode會根據文件大小和文件塊配置情況,返回給Client它所管理部分DataNode的信息。最后,Client(開發庫)將文件劃分為多個文件塊,根據DataNode的地址信息,按順序寫入到每一個DataNode塊中。
下面我們看看NameNode和DataNode扮演什么角色,有什么具體的作用:
(1)NameNode
NameNode的作用是管理文件目錄結構,是管理數據節點的。NameNode維護兩套數據:一套是文件目錄與數據塊之間的關系,另一套是數據塊與節點間的關系。前一套是靜態的,是存放在磁盤上的,通過fsimage和edits文件來維護;后一套數據時動態的,不持久化到磁盤,每當集群啟動的時候,會自動建立這些信息。
(2)DataNode
毫無疑問,DataNode是HDFS中真正存儲數據的。這里要提到一點,就是Block(數據塊)。假設文件大小是100GB,從字節位置0開始,每64MB字節劃分為一個Block,以此類推,可以劃分出很多的Block。每個Block就是64MB(也可以自定義設置Block大小)。
(3)典型部署
HDFS的一個典型部署是在一個專門的機器上運行NameNode,集群中的其他機器各運行一個DataNode。(當然,也可以在運行NameNode的機器上同時運行DataNode,或者一個機器上運行多個DataNode)一個集群中只有一個NameNode(但是單NameNode存在單點問題,在Hadoop 2.x版本之后解決了這個問題)的設計大大簡化了系統架構。
2.3 保障HDFS的可靠性措施
HDFS具備了較為完善的冗余備份和故障恢復機制,可以實現在集群中可靠地存儲海量文件。
(1)冗余備份:HDFS將每個文件存儲成一系列的數據塊(Block),默認塊大小為64MB(可以自定義配置)。為了容錯,文件的所有數據塊都可以有副本(默認為3個,可以自定義配置)。當DataNode啟動的時候,它會遍歷本地文件系統,產生一份HDFS數據塊和本地文件對應關系的列表,并把這個報告發送給NameNode,這就是報告塊(BlockReport),報告塊上包含了DataNode上所有塊的列表。
(2)副本存放:HDFS集群一般運行在多個機架上,不同機架上機器的通信需要通過交換機。通常情況下,副本的存放策略很關鍵,機架內節點之間的帶寬比跨機架節點之間的帶寬要大,它能影響HDFS的可靠性和性能。HDFS采用一種稱為機架感知(Rack-aware)的策略來改進數據的可靠性、可用性和網絡帶寬的利用率。在大多數情況下,HDFS副本系數是默認為3,HDFS的存放策略是將一個副本存放在本地機架節點上,一個副本存放在同一個機架的另一個節點上,最后一個副本放在不同機架的節點上。這種策略減少了機架間的數據傳輸,提高了寫操作的效率。機架的錯誤遠遠比節點的錯誤少,所以這種策略不會影響到數據的可靠性和可用性。
圖6.副本存放的策略
(3)心跳檢測:NameNode周期性地從集群中的每個DataNode接受心跳包和塊報告,NameNode可以根據這個報告驗證映射和其他文件系統元數據。收到心跳包,說明該DataNode工作正常。如果DataNode不能發送心跳信息,NameNode會標記最近沒有心跳的DataNode為宕機,并且不會給他們發送任何I/O請求。
(4)安全模式
(5)數據完整性檢測
(6)空間回收
(7)元數據磁盤失效
(8)快照(HDFS目前還不支持)
三.HDFS常用Shell操作
(1)列出文件目錄:hadoop fs -ls 目錄路徑
?查看HDFS根目錄下的目錄:hadoop fs -ls /
?遞歸查看HDFS根目錄下的目錄:hadoop fs -lsr /
(2)在HDFS中創建文件夾:hadoop fs -mkdir 文件夾名稱
在根目錄下創建一個名稱為di的文件夾:
(3)上傳文件到HDFS中:hadoop fs -put 本地源路徑 目標存放路徑
將本地系統中的一個log文件上傳到di文件夾中:hadoop fs -put test.log /di
*PS:我們通過Hadoop Shell上傳的文件是存放在DataNode的Block(數據塊)中的,通過Linux Shell是看不到文件的,只能看到Block。因此,可以用一句話來描述HDFS:把客戶端的大文件存放在很多節點的數據塊中。(4)從HDFS中下載文件:hadoop fs -get HDFS文件路徑 本地存放路徑
將剛剛上傳的test.log下載到本地的Desktop文件夾中:hadoop fs -get /di/test.log /home/hadoop/Desktop
(5)直接在HDFS中查看某個文件:hadoop fs -text(-cat) 文件存放路徑
在HDFS查看剛剛上傳的test.log文件:hadoop fs -text /di/test.log
(6)刪除在HDFS中的某個文件(夾):hadoop fs -rm(r) 文件存放路徑
刪除剛剛上傳的test.log文件:hadoop fs -rm /di/test.log
刪除HDFS中的di文件夾:hadoop fs -rmr /di
(7)善用help命令求幫助:hadoop fs -help 命令
查看ls命令的幫助:hadoop fs -help ls
四.使用Java操作HDFS
我們在工作中寫完的各種代碼是在服務器中運行的,HDFS的操作代碼也不例外。在開發階段,我們使用Windows下的Eclipse作為開發環境,訪問運行在虛擬機中的HDFS,也就是通過在本地的Eclipse中的Java代碼訪問遠程Linux中的HDFS。
在本地的開發調試過程中,要使用宿主機中的Java代碼訪問客戶機中的HDFS,需要確保以下幾點:宿主機和虛擬機的網絡能否互通?確保宿主機和虛擬機中的防火墻都關閉!確保宿主機與虛擬機中的jdk版本一致!?????????????????????????????????
4.1 準備工作:
(1)導入依賴jar包,如下圖所示
(2)關聯hadoop源碼項目,如下圖所示
4.2 第一個Java-HDFS程序
(1)定義HDFS_PATH:public static final String HDFS_PATH = "hdfs://hadoop-master:9000/testdir/testfile.log";
(2)讓URL類型識別hdfs://(URL類型默認只識別http://):URL.setURLStreamHandlerFactory(new FsUrlStreamHandlerFactory());
(3)具體詳細代碼如下:
1 package hdfs; 2 3 import java.io.InputStream; 4 import java.net.MalformedURLException; 5 import java.net.URL; 6 7 import org.apache.hadoop.fs.FsUrlStreamHandlerFactory; 8 import org.apache.hadoop.io.IOUtils; 9 10 public class firstApp { 11 12 public static final String HDFS_PATH = "hdfs://hadoop-master:9000/testdir/testfile.log"; 13 14 /** 15 * @param args 16 * @throws MalformedURLException 17 */ 18 public static void main(String[] args) throws Exception { 19 // TODO Auto-generated method stub 20 URL.setURLStreamHandlerFactory(new FsUrlStreamHandlerFactory()); 21 final URL url = new URL(HDFS_PATH); 22 final InputStream in = url.openStream(); 23 /** 24 * @params in 輸入流 25 * @params out 輸出流 26 * @params buffersize 緩沖區大小 27 * @params close 是否自動關閉流 28 */ 29 IOUtils.copyBytes(in, System.out, 1024, true); 30 } 31 32 } View Code? ? (4)運行結果(后面不再貼運行結果圖):
4.3 對HDFS進行CRUD編程
(1)獲得萬能的大神對象:final FileSystem fileSystem = FileSystem.get(new URI(HDFS_PATH),new Configuration());
(2)調用HDFS API進行CRUD操作,詳情見下代碼
public class FileSystemApp {private static final String HDFS_PATH = "hdfs://hadoop-master:9000/testdir/";private static final String HDFS_DIR = "/testdir/dir1";public static void main(String[] args) throws Exception {FileSystem fs = getFileSystem();// 01.創建文件夾 對應shell:mkdir createDirectory(fs);// 02.刪除文件 對應shell:hadoop fs -rm(r) xxx deleteFile(fs);// 03.上傳文件 對應shell:hadoop fs -input xxx uploadFile(fs);// 04.下載文件 對應shell:hadoop fs -get xxx xxx downloadFile(fs);// 05.瀏覽文件夾 對應shell:hadoop fs -lsr /listFiles(fs,"/");}private static void listFiles(FileSystem fs,String para) throws IOException {final FileStatus[] listStatus = fs.listStatus(new Path(para));for (FileStatus fileStatus : listStatus) {String isDir = fileStatus.isDir() ? "Directory" : "File";String permission = fileStatus.getPermission().toString();short replication = fileStatus.getReplication();long length = fileStatus.getLen();String path = fileStatus.getPath().toString();System.out.println(isDir + "\t" + permission + "\t" + replication+ "\t" + length + "\t" + path);if(isDir.equals("Directory")){listFiles(fs, path);}}}private static void downloadFile(FileSystem fs) throws IOException {final FSDataInputStream in = fs.open(new Path(HDFS_PATH + "check.log"));final FileOutputStream out = new FileOutputStream("E:\\check.log");IOUtils.copyBytes(in, out, 1024, true);System.out.println("Download File Success!");}private static void uploadFile(FileSystem fs) throws IOException {final FSDataOutputStream out = fs.create(new Path(HDFS_PATH+ "check.log"));final FileInputStream in = new FileInputStream("C:\\CheckMemory.log");IOUtils.copyBytes(in, out, 1024, true);System.out.println("Upload File Success!");}private static void deleteFile(FileSystem fs) throws IOException {fs.delete(new Path(HDFS_DIR), true);System.out.println("Delete File:" + HDFS_DIR + " Success!");}private static void createDirectory(FileSystem fs) throws IOException {fs.mkdirs(new Path(HDFS_DIR));System.out.println("Create Directory:" + HDFS_DIR + " Success!");}private static FileSystem getFileSystem() throws IOException,URISyntaxException {return FileSystem.get(new URI(HDFS_PATH), new Configuration());}} View Code參考文獻與資料
(1)傳智播客Hadoop從入門到工作視頻教程第二季:http://bbs.itcast.cn/thread-21310-1-1.html
(2)劉鵬教授,《實戰Hadoop:開啟通向云計算的捷徑》:http://item.jd.com/10830089.html
(3)吳超,《Hadoop的底層架構——RPC機制》:http://www.superwu.cn/2013/08/05/360
(4)zy19982004,《Hadoop學習十一:Hadoop-HDFS RPC總結》:http://zy19982004.iteye.com/blog/1875969
?
作者:周旭龍
出處:http://www.cnblogs.com/edisonchou/
本文版權歸作者和博客園共有,歡迎轉載,但未經作者同意必須保留此段聲明,且在文章頁面明顯位置給出原文鏈接。
轉載于:https://www.cnblogs.com/edisonchou/p/3538524.html
總結
以上是生活随笔為你收集整理的Hadoop学习笔记—2.不怕故障的海量存储:HDFS基础入门的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: java方法的定义格式
- 下一篇: 递归-汉诺塔