Hadoop-HDFS基礎原理與操做

Hadoop-HDFS基礎原理與操做

一、概述

    HDFS是Hadoop分佈式文件系統,用來分佈式存儲海量數據,並具備高可靠、高性能、可伸縮的能力。java

    HDFS屏蔽了分佈式存儲的細節,提供了標準的訪問方式,可以以相似訪問本地文件系統的方式訪問HDFS中的文件。node

    以下是HDFS的架構圖:shell

    

    1.namenode 管理元數據數據庫

    2.datanode 存儲文件塊apache

    3.Block 文件塊,BlockSize 128MBwindows

    4.Replication 文件塊的副本安全

    5.Rack 機架bash

    6.Client 經過API後指令操做的一端(好比上傳或下載文件,操做文件)服務器

二、HDFS的相關操做

    能夠經過shell或JavaAPI方式操做HDFS中的數據。架構

1.shell命令

    hdfs中的數據,一次寫入、屢次讀取、不支持行級別的增刪改。2.0版本增長了在文件中追加的內容的功能。因此也沒有對應的行級別的命令。

hadoop fs -ls /user #查看目錄。
hadoop fs -mkdir /user/trunk #建立目錄。
hadoop fs -lsr /user #遞歸查看目錄。
hadoop fs -put test.txt /user/trunk #上傳文件。
hadoop fs -put test.txt #複製到hdfs當前目錄下,首先要建立當前目錄。
hadoop fs -get /user/trunk/test.txt #複製到本地當前目錄下,即下載到本地當前目錄
hadoop fs -cat /user/trunk/test.txt #查看文件內容。
hadoop fs -tail /user/trunk/test.txt #監控,查看最後1000字節。
hadoop fs -rm /user/trunk/test.txt #刪除文件。
hadoop fs -rmdir /user/trunk #刪除目錄。
hadoop fs -help ls #查看ls命令的幫助文檔。

2.Eclipse中Hadoop插件的使用

1>安裝單機模式

    在Windows環境下,解壓一個Hadoop的安裝包,做爲Windows下的Hadoop單機模式使用。

    若是要使用遠程的Hadoop須要配置Windows下的Hadoop的環境變量,以及用戶名的環境變量。配置此項可能須要重啓電腦。

    內容以下:

HADOOP_HOME=路徑
PATH=%HADOOP_HOME%/bin;%HADOOP_HOME%/sbin
HADOOP_USER_NAME=root

2>添加插件

    將插件文件hadoop-eclipse-plugin-2.7.1.jar放入eclipse/plugins目錄下,重啓eclipse。

3>配置Eclipse

    在Window的preferences中找到Hadoop Map/Reduce,將單機模式的Hadoop路徑填入,以下如所示:

在Eclipse中找到以下界面,將Map/Reduce模式顯示出來。

    在Hadoop的配置界面,填入以下數據:

    Location name:填寫安裝Hadoop服務器的主機名。

    Map/Reduce(V2)Master Host:填寫安裝Hadoop服務器的主機名。

    DFS Master Port:改成安裝Hadoop服務器核心配置文件中配置的端口號,通常默認爲9000。

    User name:安裝Hadoop服務器的超級管理員,通常爲root。

    配置完成點擊Finish。而後就可使用了。

4>問題

    當遇到權限拒絕問題時,能夠修改hdfs-site.xml中的配置dfs.permissions爲false關閉hadoop的權限認證。

    也能夠在windows的環境變量中配置HADOOP_USER_NAME指定鏈接hadoop時使用的名稱,這種方式配置完要重啓eclipse。

3.HDFS的Java API

1>導入jar

    hadoop/share/hadoop/common/*.jar

    hadoop/share/hadoop/common/lib/*.jar

    hadoop/share/hadoop/hdfs/*.jar

2>FileSystem

    文件系統類,HDFS API的主要類,全部相關操做基本都在這個類裏。

重要方法

1)get(URI uri,Configuration conf);

    獲取一個FileSystem對象。

2)open(Path path);

    打開鏈接。返回一個InputStream對象。

3)create(Path path);

    建立一個文件。返回一個OutputStream對象。

4)delete(Path path,boolean recursive);

    是否遞歸刪除一個文件或路徑。返回boolean值,刪除成功返回true,刪除失敗返回false。

5)mkdirs(Path path);

    建立文件夾,能夠建立多級目錄。返回boolean值,建立成功返回true,建立失敗返回false。

3>IOUtils

    HDFS相關操做的一個工具類。

重要方法

1)copyBytes(InputStream in,OutputStream out,int buffersize);

    對接數據,將輸入輸出流整合,直接將文件傳輸到目的地。

4>代碼演示

@Test
	public void mkdir() throws Exception {
		FileSystem fs = FileSystem.get(new URI("hdfs://yun01:9000"), new Configuration());
		fs.mkdirs(new Path("/test2/xx/yy/zzz"));
		fs.close();
	}

	@Test
	public void delete() throws Exception {
		// 1.建立文件系統對象
		FileSystem fs = FileSystem.get(new URI("hdfs://yun01:9000"), new Configuration());
		// 2.刪除文件
		// fs.delete(new Path("/test/3.txt"));
		fs.delete(new Path("/test/1.txt"), true);
		// 3.關閉鏈接
		fs.close();
	}

	@Test
	public void upload() throws Exception {
		// 1.建立文件系統對象
		FileSystem fs = FileSystem.get(new URI("hdfs://yun01:9000"), new Configuration());
		// 2.建立文件
		FSDataOutputStream out = fs.create(new Path("/test/3.txt"));
		// 3.建立輸入流
		InputStream in = new FileInputStream("2.txt");
		// 4.對接流
		IOUtils.copyBytes(in, out, 1024);
		// 5.關閉流關閉文件系統
		in.close();
		out.close();
		fs.close();
	}

	@Test
	public void download() throws Exception {
		// 1.建立文件系統對象
		FileSystem fs = FileSystem.get(new URI("hdfs://yun01:9000"), new Configuration());
		// 2.獲取鏈接文件的流
		FSDataInputStream in = fs.open(new Path("/test/jt-對象存儲地址.txt"));
		// 3.建立輸出流
		OutputStream out = new FileOutputStream("2.txt");
		// 對接流,傳輸數據
		IOUtils.copyBytes(in, out, 1024);
		// 5.關閉流,關閉鏈接
		out.close();
		in.close();
		fs.close();
	}

三、HDFS技術細節

1.HDFS的主要原理

    將數據進行切塊後進行復制並存儲在集羣的多個節點中,從而實現了海量數據分佈式存儲,並經過block副本實現可靠性保證。

    其中切出的塊稱爲Block。

    負責存放Block的節點稱之爲DataNode節點。

    負責存放元數據的節點稱之爲NameNode節點。

    另外還有一個獨立進程稱做SecondaryNameNode負責幫助NameNode進行元數據的合併操做。

2.Block

    Block是HDFS中存儲的基本單位。

    當文件被存儲到HDFS的過程當中,會先將文件按照指定大小來切塊即block,複製出指定數量的副本(默認是3個),分佈式存儲在集羣中。2.0版本中Block默認的大小爲128M,1.0版本中爲64M。

1> 文件切塊目的

    1.一個大文件切分爲小的若干個Block方便分佈式的存儲在不一樣磁盤中。

    2.屏蔽了數據的區別,只須要面向Block操做,從而簡化存儲系統。

    3.有利於數據的複製。每次複製的是一個體積較小的Block,而不是一個大型文件,效率更高。

    若是切分事後,剩餘數據不夠128MB,則會將剩餘數據單獨做爲一個Block存儲,數據多大,Block就多大,128MB只是最大大小,不是固定大小。

    例如:

    一個256MB文件,共有256/128=2個Block。

    一個258MB文件,共有258/128=2餘下2MB,則餘下的2MB會獨佔一個Block大小爲2MB,則且分出兩個128MB的Block和一個2MB的Block。

    一個1MB文件,則單獨佔用一個Block,這個Block爲1MB大小。

2>Block副本放置策略

    第一個副本:若是是集羣內提交,就放置在上傳文件的DataNode,若是是集羣外就提交,隨機選擇一臺磁盤不太滿,cpu不太忙的節點,進行上傳。

    第二個副本:放置在第一個副本不一樣機架的節點上。(利用機架感知策略)

    第三個副本:放置在與第二個副本相同機架的節點上。

    更多副本:隨機節點。

    機架感知策略:

    其實就是在Hadoop的配置文件中添加一個記錄ip和主機名映射機架的關係表,經過這張關係表來判斷那個主機是不一樣機架。

 

3.DataNode

    DataNode在整個HDFS中主要是存儲數據的功能。數據以Block的形式存放在DataNode中。

    DataNode節點會不斷向NameNode節點發送心跳報告保持與其聯繫,心跳報告的頻率是3秒一次,在心跳報告中向NameNode報告信息,從心跳響應中接受NameNode的指令,執行對塊的複製、移動、刪除等操做。

    NameNode若是10分鐘都沒收到DataNode的心跳,則認爲該DataNode已經lost,並向其餘DataNode發送備份block的指令,完成lost節點中的數據副本的複製,以保證數據副本數量在整個HDFS中是一致的。

    全部的DataNode都是主動聯繫NameNode,NameNode不會主動聯繫DataNode。

4.NameNode

    NameNode維護着HDFS中的元數據信息。同時還兼顧各類外部請求以及DataNode中數據存儲的管理。

    元數據信息包括:文件信息、目錄結構信息、副本數量信息、文件和Block之間關係的信息、Block和DataNode之間的關係信息。數據格式參照以下:

    FileName replicas block-Ids id2host

    例如:/test/a.log,3,{b1,b2},[{b1:[h0,h1,h3]},{b2:[h0,h2,h4]}]

1>元數據的存儲

    NameNode中的元數據信息存儲在內存和文件中,內存中爲實時信息完整信息,文件中爲數據鏡像做爲持久化存儲使用,其中block和DataNode之間的關係信息不會在文件中存儲。

內存中的元數據

    文件信息、目錄結構信息、副本數量信息、文件和Block之間關係的信息、Block和DataNode之間的關係信息。

文件中的元數據

    文件信息、目錄結構信息、副本數量信息、文件和Block之間關係的信息。

    能夠發現文件中的元數據比起內存中缺失了block和DataNode之間的對應關係,這是由於,HDFS集羣常常發生變更,DataNode增長或減小都是很正常狀況,所以這些信息都是臨時在內存中組織的,而不會存儲在磁盤鏡像文件中。

2> NameNode的文件

fsimage

    元數據鏡像文件。存儲某NameNode元數據信息,並非實時同步內存中的數據。

edits

    記錄NameNode對數據操做的日誌文件。

fstime

    保存最近一次checkpoint的時間。即最後一次元數據合併的時間。

3>工做原理

    當有寫請求時,NameNode會首先將請求操做寫edit log到磁盤edits文件中,成功後纔會修改內存,並向客戶端返回操做結果。

    因此,fsimage中的數據並非實時的數據,而是在達到條件時要和edits文件合併,合併過程由SecondaryNameNode完成。

    之因此不直接改fsimage而是要在edits中記錄,是由於記錄日誌是一種連續的磁盤IO操做,能夠節省時間。若是直接修改fsimage文件,會進行大量的不連續的磁盤IO操做,這樣會大大下降效率。

5.SecondaryNameNode

    這個是爲分佈式纔有的角色,在徹底分佈式中,由JournalNode代替。

    SecondaryNameNode並非NameNode的熱備份,而是協助者,幫助NameNode進行元數據的合併。

    從另外的角度來看能夠提供必定的備份功能,但並非熱備,若是直接使用可能會丟失上一次合併後發生的數據!能夠從SecondaryNameNode中恢復部分數據,可是沒法恢復所有。

1>合併數據的條件

    什麼時候出發數據合併?

    根據配置文件設置的時間間隔:fs.checkpoint.period默認3600秒。

    根據配置文件設置的edits log大小:fs.checkpoint.size默認64MB。

2>合併過程

拷貝文件

    當達到合併數據的條件後,SecondrayNameNode會將NameNode中的fsimage和edits文件拷貝過來,同時NameNode中會建立一個新的edits.new文件,用於記錄新的讀寫請求。

合併數據

    在SecondrayNameNode中將拷貝過來的fsimage和edits合併爲一個新的fsimage.ckpt文件。

傳回數據

    SecondrayNameNode將合併完成的fsimage.ckpt文件拷貝回NameNode中,而後刪除以前的fsimage文件,將fsimage.ckpt文件改名爲fsimage,NameNode將原來edtis文件刪除,再將edtis.new改成edits,完成合並工做。

記錄合併操做

    最後在fstime文件中添加此次合併的記錄。

    因爲NameNode實時數據都在內存中,此處的合併指的是磁盤中的持久化的數據的處理。

3>應用

    判斷:snn能夠對元數據作必定程度的備份,可是不是熱備,對不對?

    思考:什麼狀況下可能形成NameNode元數據信息丟失?

    snn並非nn的熱備,可是能保存大部分備份數據。緣由就在於edits.new中的數據丟失了就找不回來了

一般NameNode和SecondrayNameNode要放置到不一樣機器中以此提高性能,並提供必定的元數據安全性。

 

四、HDFS執行流程

    針對HDFS的不一樣操做,有不一樣的執行流程,具體介紹以下。

1.HDFS讀流程

1>發送請求

    使用HDFS提供的客戶端開發庫Client,向遠程的Namenode發起RPC請求;NameNode會檢驗當前文件是否存在以及當前客戶端是否有權限讀取該文件,兩種檢查只中有一種不符合條件,就會拋出異常,再也不進行下一步操做。

2>響應資源元數據

    若是以上校驗沒有問題,Namenode會視狀況返回文件的部分或者所有block列表,對於每一個block,Namenode都會返回有該block副本的DataNode地址。

3>下載資源

    客戶端開發庫Client會選取離客戶端最接近(並非物理上的最近,而是延遲最低負載最低)的DataNode來讀取block;若是客戶端自己就是DataNode,那麼將從本地直接獲取數據。

4>資源校驗

    讀取完當前block的數據後,會進行checksum驗證,若是讀取datanode時出現錯誤,客戶端會通知Namenode,而後再從下一個擁有該block拷貝的datanode繼續讀。

    當讀取正確的block數據以後,關閉與當前的DataNode鏈接,併爲讀取下一個block尋找最佳的DataNode;當讀完列表的block後,且文件讀取尚未結束,客戶端開發庫會繼續向Namenode獲取下一批的block列表。

5>下載結束告知

    當文件最後一個塊也都讀取完成後,datanode會鏈接namenode告知關閉文件。

NameNode不參與讀取真實數據傳輸的過程。

2.HDFS的寫流程

1>發送請求

    使用HDFS提供的客戶端開發庫Client,向遠程的Namenode發起RPC請求;Namenode會檢查要建立的文件是否已經存在,建立者是否有權限進行操做,若是這兩個條件有一個不符合就會讓客戶端拋出異常,終止操做。條件驗證經過則會爲文件建立一個記錄。

2>數據切塊

    當客戶端開始寫入文件的時候,開發庫客戶端會將文件切分紅多個packets,並在內部以數據隊列"data queue"的形式管理這些packets,而後向Namenode申請新的blocks,獲取用來存儲replicas的合適的datanodes列表,列表的大小根據在Namenode中對replication的設置而定。

3>上傳數據

    根據DataNode列表鏈接DataNode節點,開始以pipeline(管道)的形式將packet寫入全部的replicas中。客戶端把packet以流的方式寫入第一個datanode,該datanode把該packet存儲以後,再將其傳遞給在此pipeline中的下一個datanode,直到最後一個datanode完成存儲,這種寫數據的方式呈流水線的形式。

4>響應上傳結果

    最後一個datanode成功存儲以後會返回一個ack packet,在pipeline裏傳遞至客戶端,在客戶端的開發庫內部維護着"ack queue",成功收到datanode返回的ack packet後會從"ack queue"移除相應的packet。

    若是傳輸過程當中,有某個datanode出現了故障,那麼當前的pipeline會被關閉,出現故障的datanode會從當前的pipeline中移除,剩餘的block會繼續剩下的datanode中繼續以pipeline的形式傳輸,同時Namenode會分配一個新的datanode,保持replicas設定的數量。

5>上傳結果告知

    當全部的packges都成功的上傳後,客戶端通知NameNoe文件上傳完成,NameNode將該文件置爲可用狀態,並關閉該文件。

    NameNode不參與真實數據存儲傳輸的過程。

 

3.HDFS的刪除流程

1>發送請求

    客戶端發起請求鏈接NameNode表示要刪除文件,NameNode檢查文件是否存在及是否有權限刪除文件,若是條件驗證不經過,那麼拋出異常,終止操做。若是經過則進行下一步操做。

2>執行僞刪除操做並響應

    NameNode執行元數據的刪除,只是將該元數據置爲已刪除狀態,而後向客戶端表示文件刪除成功。

3>發佈刪除指令

    當保存着這些數據塊的DataNode節點向NameNode節點發送心跳時,在心跳響應中,NameNode節點會向DataNode發出指令,要求刪除這些block。DataNode收到指令後刪除對應的Block。因此在執行完delete方法後的一段時間內,數據塊才能被真正的刪除掉。

4>完全刪除

    當該文件對應的全部block及其副本都被刪除後,NameNode中將以前標記爲已刪除的元數據刪除。

 

4.HDFS的啓動流程

1>導入元數據

    在HDFS啓動時,NameNode先合併fsImage和edits文件,生成新的fsimage和空的edits文件,這個過程是NameNode本身進行的。而後再將fsimage中的數據恢復到內存中,但此時內存中的元數據並不夠,還差block和datanode的映射關係,這個信息在fsimage中是不存在的,須要臨時在內存中組織出來。

2>整合元數據

    此時NameNode等待DataNode的鏈接,DataNode在啓動時會向NameNode發送心跳報告,其中攜帶本身具備的Block的編號信息,NameNode基於這些信息,在內存中組織元數據信息。

3>開啓服務

    直到NameNode達到最小啓動條件後,進行必要的block副本複製和刪除,以後開始對外提供服務。整個這個過程當中,HDFS沒法正常工做,稱之爲處在安全模式中。

NameNode最小啓動條件:每一個Block都至少有了一個副本被找到。

5.安全模式

    在啓動HDFS時,會當即進入安全模式,此時不能操做hdfs中的文件,只能查看目錄文件名等,讀寫操做都不能進行。

    在HDFS正常運行過程當中,若是由於意外狀況,形成有block找不到任何副本,則HDFS進入安全模式。

org.apache.hadoop.dfs.SafeModeException: Cannot delete /user/hadoop/input. Name node is in safe mode

    安全模式實際上是HDFS對元數據的一種保護機制,防止意外的操做損壞元數據。

    當遇到安全模式,最簡單的辦法就是等一會。

    若是很長時間都沒法退出安全模式,則應檢查進入安全模式的緣由,找到問題的緣由解決,則hadoop會自動退出安全模式。

    若是非要強制退出安全模式,可使用以下命令,可是要慎用,一不當心損壞了元數據,hdsf中的數據就都沒法使用了:

hadoop dfsadmin -safemode leave

    慎用!

五、HDFS的優缺點

1.HDFS優勢

1> 支持超大文件

    支持超大文件。超大文件在這裏指的是幾百M,幾百GB,甚至幾TB大小的文件。通常來講hadoop的文件系統會存儲TB級別或者PB級別的數據。因此在企業的應用中,數據節點有可能有上千個。

2>檢測和快速應對硬件故障

    在集羣的環境中,硬件故障是常見的問題。由於有上千臺服務器鏈接在一塊兒,這樣會致使高故障率。所以故障檢測和自動恢復是HDFS文件系統的一個設計目標。

3>流式數據訪問

    HDFS的數據處理規模比較大,應用一次須要訪問大量的數據,同時這些應用通常都是批量處理,而不是用戶交互式處理。應用程序能以流的形式訪問數據集。主要的是數據的吞吐量,而不是訪問速度。

4>簡化的一致性模型

    大部分HDFS操做文件時,須要一次寫入,屢次讀取。在HDFS中,一個文件一旦通過建立、寫入、關閉後,通常就不須要修改了。這樣簡單的一致性模型,有利於提升吞吐量。

5>高容錯性

    數據自動保存多個副本,副本丟失後自動恢復。

6>可構建在廉價機器上

    構建在廉價機器上,能夠輕鬆的經過擴展機器數量,來近乎線性的提升集羣存儲能力。

 

2.HDFS缺點

1>不能作到低延遲數據訪問

    低延遲數據如:和用戶進行交互的應用,須要數據在毫秒或秒的範圍內獲得響應。因爲hadoop針對高數據吞吐量作了優化,犧牲了獲取數據的延遲,因此對於低延遲來講,不適合用hadoop來作。

2>大量的小文件會影響性能

    HDFS支持超大的文件,是經過數據分佈在數據節點,數據的元數據保存在名字節點上。名字節點的內存大小,決定了HDFS文件系統可保存的文件數量。雖然如今的系統內存都比較大,但大量的小文件仍是會影響名字節點的性能。

3>不支持多用戶寫入文件、修改文件

    HDFS的文件只能有一次寫入,不支持修改和追加寫入(2.0版本支持追加),也不支持修改。只有這樣數據的吞吐量才能大。

4>不支持超強的事務

    沒有像關係型數據庫那樣,對事務有強有力的支持。

 

上一篇:Hadoop徹底分佈式集羣搭建

下一篇:Hadoop-MapReduce基本原理及相關操做

相關文章
相關標籤/搜索