【史上最全】Hadoop 核心 - HDFS 分散式檔案系統詳解(上萬字建議收藏)

五分鐘學大資料發表於2021-02-08

1. HDFS概述

Hadoop 分散式系統框架中,首要的基礎功能就是檔案系統,在 Hadoop 中使用 FileSystem 這個抽象類來表示我們的檔案系統,這個抽象類下面有很多子實現類,究竟使用哪一種,需要看我們具體的實現類,在我們實際工作中,用到的最多的就是HDFS(分散式檔案系統)以及LocalFileSystem(本地檔案系統)了。

在現代的企業環境中,單機容量往往無法儲存大量資料,需要跨機器儲存。統一管理分佈在叢集上的檔案系統稱為分散式檔案系統

HDFS(Hadoop Distributed File System)是 Hadoop 專案的一個子專案。是 Hadoop 的核心元件之一, Hadoop 非常適於儲存大型資料 (比如 TB 和 PB),其就是使用 HDFS 作為儲存系統. HDFS 使用多臺計算機儲存檔案,並且提供統一的訪問介面,像是訪問一個普通檔案系統一樣使用分散式檔案系統。

HDFS檔案系統

2. HDFS架構

HDFS架構

HDFS是一個主/從(Mater/Slave)體系結構,由三部分組成: NameNodeDataNode 以及 SecondaryNamenode

  • NameNode 負責管理整個檔案系統的後設資料,以及每一個路徑(檔案)所對應的資料塊資訊。

  • DataNode 負責管理使用者的檔案資料塊,每一個資料塊都可以在多個 DataNode 上儲存多個副本,預設為3個。

  • Secondary NameNode 用來監控 HDFS 狀態的輔助後臺程式,每隔一段時間獲取 HDFS 後設資料的快照。最主要作用是輔助 NameNode 管理後設資料資訊

3. HDFS的特性

首先,它是一個檔案系統,用於儲存檔案,通過統一的名稱空間目錄樹來定位檔案;

其次,它是分散式的,由很多伺服器聯合起來實現其功能,叢集中的伺服器有各自的角色。

  • 1. master/slave 架構(主從架構)

HDFS 採用 master/slave 架構。一般一個 HDFS 叢集是有一個 Namenode 和一定數目的 Datanode 組成。Namenode 是 HDFS 叢集主節點,Datanode 是 HDFS 叢集從節點,兩種角色各司其職,共同協調完成分散式的檔案儲存服務。

  • 2. 分塊儲存

HDFS 中的檔案在物理上是分塊儲存(block)的,塊的大小可以通過配置引數來規定,預設大小在 hadoop2.x 版本中是 128M。

  • 3. 名字空間(NameSpace)

HDFS 支援傳統的層次型檔案組織結構。使用者或者應用程式可以建立目錄,然後將檔案儲存在這些目錄裡。檔案系統名字空間的層次結構和大多數現有的檔案系統類似:使用者可以建立、刪除、移動或重新命名檔案。
Namenode 負責維護檔案系統的名字空間,任何對檔案系統名字空間或屬性的修改都將被 Namenode 記錄下來。
HDFS 會給客戶端提供一個統一的抽象目錄樹,客戶端通過路徑來訪問檔案,形如:hdfs://namenode:port/dir-a/dir-b/dir-c/file.data。

  • 4. NameNode 後設資料管理

我們把目錄結構及檔案分塊位置資訊叫做後設資料。NameNode 負責維護整個 HDFS 檔案系統的目錄樹結構,以及每一個檔案所對應的 block 塊資訊(block 的 id,及所在的 DataNode 伺服器)。

  • 5. DataNode 資料儲存

檔案的各個 block 的具體儲存管理由 DataNode 節點承擔。每一個 block 都可以在多個 DataNode 上。DataNode 需要定時向 NameNode 彙報自己持有的 block 資訊。 儲存多個副本(副本數量也可以通過引數設定 dfs.replication,預設是 3)

  • 6. 副本機制

為了容錯,檔案的所有 block 都會有副本。每個檔案的 block 大小和副本系數都是可配置的。應用程式可以指定某個檔案的副本數目。副本系數可以在檔案建立的時候指定,也可以在之後改變。

  • 7. 一次寫入,多次讀出

HDFS 是設計成適應一次寫入,多次讀出的場景,且不支援檔案的修改。
正因為如此,HDFS 適合用來做大資料分析的底層儲存服務,並不適合用來做網盤等應用,因為修改不方便,延遲大,網路開銷大,成本太高。

4. HDFS 的命令列使用

如果沒有配置 hadoop 的環境變數,則在 hadoop 的安裝目錄下的bin目錄中執行以下命令,如已配置 hadoop 環境變數,則可在任意目錄下執行

help

格式:  hdfs dfs -help 操作命令
作用: 檢視某一個操作命令的引數資訊

ls

格式:hdfs dfs -ls  URI
作用:類似於Linux的ls命令,顯示檔案列表

lsr

格式  :   hdfs  dfs -lsr URI
作用  : 在整個目錄下遞迴執行ls, 與UNIX中的ls-R類似

mkdir

格式 : hdfs  dfs  -mkdir [-p] <paths>
作用 :   以<paths>中的URI作為引數,建立目錄。使用-p引數可以遞迴建立目錄

put

格式   : hdfs dfs -put <localsrc >  ... <dst>
作用 :  將單個的原始檔src或者多個原始檔srcs從本地檔案系統拷貝到目標檔案系統中(<dst>對應的路徑)。也可以從標準輸入中讀取輸入,寫入目標檔案系統中
hdfs dfs -put  /rooot/bigdata.txt  /dir1

moveFromLocal

格式: hdfs  dfs -moveFromLocal  <localsrc>   <dst>
作用:  和put命令類似,但是原始檔localsrc拷貝之後自身被刪除
hdfs  dfs -moveFromLocal  /root/bigdata.txt  /

copyFromLocal

格式:  hdfs dfs -copyFromLocal <localsrc> ... <dst>
作用: 從本地檔案系統中拷貝檔案到hdfs路徑去

appendToFile

格式: hdfs dfs -appendToFile <localsrc> ... <dst>
作用: 追加一個或者多個檔案到hdfs指定檔案中.也可以從命令列讀取輸入.
 hdfs dfs -appendToFile  a.xml b.xml  /big.xml

moveToLocal

在 hadoop 2.6.4 版本測試還未未實現此方法
格式:hadoop  dfs  -moveToLocal [-crc] <src> <dst>
作用:將本地檔案剪下到 HDFS

get

格式   hdfs dfs  -get [-ignorecrc ]  [-crc]  <src> <localdst>

作用:將檔案拷貝到本地檔案系統。 CRC 校驗失敗的檔案通過-ignorecrc選項拷貝。 檔案和CRC校驗可以通過-CRC選項拷貝
hdfs dfs  -get   /bigdata.txt  /export/servers

getmerge

格式: hdfs dfs -getmerge <src> <localdst>
作用: 合併下載多個檔案,比如hdfs的目錄 /aaa/下有多個檔案:log.1, log.2,log.3,...

copyToLocal

格式:  hdfs dfs -copyToLocal <src> ... <localdst>
作用:  從hdfs拷貝到本地

mv

格式  : hdfs  dfs -mv URI   <dest>
作用: 將hdfs上的檔案從原路徑移動到目標路徑(移動之後檔案刪除),該命令不能跨檔案系統
hdfs  dfs  -mv  /dir1/bigdata.txt   /dir2

rm

格式: hdfs dfs -rm [-r] 【-skipTrash】 URI 【URI 。。。】
作用: 刪除引數指定的檔案,引數可以有多個。  此命令只刪除檔案和非空目錄。
如果指定-skipTrash選項,那麼在回收站可用的情況下,該選項將跳過回收站而直接刪除檔案;
否則,在回收站可用時,在HDFS Shell 中執行此命令,會將檔案暫時放到回收站中。
hdfs  dfs  -rm  -r  /dir1

cp

格式: hdfs  dfs  -cp URI [URI ...] <dest>
作用: 將檔案拷貝到目標路徑中。如果<dest>  為目錄的話,可以將多個檔案拷貝到該目錄下。
-f
選項將覆蓋目標,如果它已經存在。
-p
選項將保留檔案屬性(時間戳、所有權、許可、ACL、XAttr)。
hdfs dfs -cp /dir1/a.txt  /dir2/bigdata.txt

cat

hdfs dfs  -cat  URI [uri  ...]
作用:將引數所指示的檔案內容輸出到stdout
hdfs dfs  -cat /bigdata.txt

tail

格式: hdfs dfs -tail path
作用: 顯示一個檔案的末尾

text

格式:hdfs dfs -text path
作用: 以字元形式列印一個檔案的內容

chmod

格式:hdfs  dfs  -chmod  [-R]  URI[URI  ...]
作用:改變檔案許可權。如果使用  -R 選項,則對整個目錄有效遞迴執行。使用這一命令的使用者必須是檔案的所屬使用者,或者超級使用者。
hdfs dfs -chmod -R 777 /bigdata.txt

chown

格式:  hdfs  dfs  -chmod  [-R]  URI[URI ...]
作用:  改變檔案的所屬使用者和使用者組。如果使用  -R 選項,則對整個目錄有效遞迴執行。使用這一命令的使用者必須是檔案的所屬使用者,或者超級使用者。
hdfs  dfs  -chown  -R hadoop:hadoop  /bigdata.txt

df

格式: hdfs dfs  -df  -h  path
作用: 統計檔案系統的可用空間資訊

du

格式: hdfs dfs -du -s -h path
作用: 統計資料夾的大小資訊

count

格式: hdfs dfs -count path
作用: 統計一個指定目錄下的檔案節點數量

setrep

格式:  hdfs dfs -setrep num filePath
作用: 設定hdfs中檔案的副本數量
注意: 即使設定的超過了datanode的數量,副本的數量也最多隻能和datanode的數量是一致的

expunge (慎用)

格式:  hdfs dfs  -expunge
作用: 清空hdfs垃圾桶 

5. hdfs的高階使用命令

5.1. HDFS檔案限額配置

在多人共用HDFS的環境下,配置設定非常重要。特別是在 Hadoop 處理大量資料的環境,如果沒有配額管理,很容易把所有的空間用完造成別人無法存取。HDFS 的配額設定是針對目錄而不是針對賬號,可以讓每個賬號僅操作某一個目錄,然後對目錄設定配置

HDFS 檔案的限額配置允許我們以檔案個數,或者檔案大小來限制我們在某個目錄下上傳的檔案數量或者檔案內容總量,以便達到我們類似百度網盤網盤等限制每個使用者允許上傳的最大的檔案的量。

 hdfs dfs -count -q -h /user/root/dir1  #檢視配額資訊

結果:

5.1.1. 數量限額

hdfs dfs  -mkdir -p /user/root/dir    #建立hdfs資料夾
hdfs dfsadmin -setQuota 2  dir      # 給該資料夾下面設定最多上傳兩個檔案,發現只能上傳一個檔案

hdfs dfsadmin -clrQuota /user/root/dir  # 清除檔案數量限制

5.1.2. 空間大小限額

在設定空間配額時,設定的空間至少是 block_size * 3 大小

hdfs dfsadmin -setSpaceQuota 4k /user/root/dir   # 限制空間大小4KB
hdfs dfs -put  /root/a.txt  /user/root/dir 

生成任意大小檔案的命令:

dd if=/dev/zero of=1.txt  bs=1M count=2     #生成2M的檔案

清除空間配額限制

hdfs dfsadmin -clrSpaceQuota /user/root/dir

5.2. HDFS 的安全模式

安全模式是hadoop的一種保護機制,用於保證叢集中的資料塊的安全性。當叢集啟動的時候,會首先進入安全模式。當系統處於安全模式時會檢查資料塊的完整性。

假設我們設定的副本數(即引數dfs.replication)是3,那麼在datanode上就應該有3個副本存在,假設只存在2個副本,那麼比例就是2/3=0.666。hdfs預設的副本率0.999。我們的副本率0.666明顯小於0.999,因此係統會自動的複製副本到其他dataNode,使得副本率不小於0.999。如果系統中有5個副本,超過我們設定的3個副本,那麼系統也會刪除多於的2個副本。

在安全模式狀態下,檔案系統只接受讀資料請求,而不接受刪除、修改等變更請求。在,當整個系統達到安全標準時,HDFS自動離開安全模式。30s

安全模式操作命令

    hdfs  dfsadmin  -safemode  get #檢視安全模式狀態
    hdfs  dfsadmin  -safemode  enter #進入安全模式
    hdfs  dfsadmin  -safemode  leave #離開安全模式

6. HDFS 的 block 塊和副本機制

HDFS 將所有的檔案全部抽象成為 block 塊來進行儲存,不管檔案大小,全部一視同仁都是以 block 塊的統一大小和形式進行儲存,方便我們的分散式檔案系統對檔案的管理。

所有的檔案都是以 block 塊的方式存放在 hdfs 檔案系統當中,在 Hadoop 1 版本當中,檔案的 block 塊預設大小是 64M,Hadoop 2 版本當中,檔案的 block 塊大小預設是128M,block塊的大小可以通過 hdfs-site.xml 當中的配置檔案進行指定。

<property>
    <name>dfs.block.size</name>
    <value>塊大小 以位元組為單位</value> //只寫數值就可以
</property>

6.1 抽象為block塊的好處

    1. 一個檔案有可能大於叢集中任意一個磁碟
      10T*3/128 = xxx塊 2T,2T,2T 檔案方式存—–>多個block塊,這些block塊屬於一個檔案
    1. 使用塊抽象而不是檔案可以簡化儲存子系統
    1. 塊非常適合用於資料備份進而提供資料容錯能力和可用性

6.2 塊快取

通常 DataNode 從磁碟中讀取塊,但對於訪問頻繁的檔案,其對應的塊可能被顯示的快取在 DataNode 的記憶體中,以堆外塊快取的形式存在。預設情況下,一個塊僅快取在一個DataNode的記憶體中,當然可以針對每個檔案配置DataNode的數量。作業排程器通過在快取塊的DataNode上執行任務,可以利用塊快取的優勢提高讀操作的效能

例如:
連線(join)操作中使用的一個小的查詢表就是塊快取的一個很好的候選。 使用者或應用通過在快取池中增加一個cache directive來告訴namenode需要快取哪些檔案及存多久。快取池(cache pool)是一個擁有管理快取許可權和資源使用的管理性分組。

例如:

一個檔案 130M,會被切分成2個block塊,儲存在兩個block塊裡面,實際佔用磁碟130M空間,而不是佔用256M的磁碟空間

6.3 hdfs的檔案許可權驗證

hdfs的檔案許可權機制與linux系統的檔案許可權機制類似

r:read w:write x:execute
許可權x對於檔案表示忽略,對於資料夾表示是否有許可權訪問其內容

如果linux系統使用者zhangsan使用hadoop命令建立一個檔案,那麼這個檔案在HDFS當中的owner就是zhangsan

HDFS檔案許可權的目的,防止好人做錯事,而不是阻止壞人做壞事。HDFS相信你告訴我你是誰,你就是誰

6.4 hdfs的副本因子

為了保證block塊的安全性,也就是資料的安全性,在hadoop2當中,檔案預設儲存三個副本,我們可以更改副本數以提高資料的安全性

、在hdfs-site.xml當中修改以下配置屬性,即可更改檔案的副本數

<property>
     <name>dfs.replication</name>
     <value>3</value>
</property>

7. HDFS 檔案寫入過程(非常重要)

HDFS 檔案寫入過程

  1. Client 發起檔案上傳請求,通過 RPC 與 NameNode 建立通訊, NameNode 檢查目標檔案是否已存在,父目錄是否存在,返回是否可以上傳;

  2. Client 請求第一個 block 該傳輸到哪些 DataNode 伺服器上;

  3. NameNode 根據配置檔案中指定的備份數量及機架感知原理進行檔案分配, 返回可用的 DataNode 的地址如:A, B, C;

Hadoop 在設計時考慮到資料的安全與高效, 資料檔案預設在 HDFS 上存放三份, 儲存策略為本地一份,同機架內其它某一節點上一份,不同機架的某一節點上一份。

  1. Client 請求 3 臺 DataNode 中的一臺 A 上傳資料(本質上是一個 RPC 呼叫,建立 pipeline ),A 收到請求會繼續呼叫 B,然後 B 呼叫 C,將整個 pipeline 建立完成, 後逐級返回 client;

  2. Client 開始往 A 上傳第一個 block(先從磁碟讀取資料放到一個本地記憶體快取),以 packet 為單位(預設64K),A 收到一個 packet 就會傳給 B,B 傳給 C。A 每傳一個 packet 會放入一個應答佇列等待應答;

  3. 資料被分割成一個個 packet 資料包在 pipeline 上依次傳輸,在 pipeline 反方向上, 逐個傳送 ack(命令正確應答),最終由 pipeline 中第一個 DataNode 節點 A 將 pipelineack 傳送給 Client;

  4. 當一個 block 傳輸完成之後,Client 再次請求 NameNode 上傳第二個 block,重複步驟 2;

7.1 網路拓撲概念

在本地網路中,兩個節點被稱為“彼此近鄰”是什麼意思?在海量資料處理中,其主要限制因素是節點之間資料的傳輸速率——頻寬很稀缺。這裡的想法是將兩個節點間的頻寬作為距離的衡量標準。

節點距離:兩個節點到達最近的共同祖先的距離總和。

例如,假設有資料中心d1機架r1中的節點n1。該節點可以表示為/d1/r1/n1。利用這種標記,這裡給出四種距離描述。

Distance(/d1/r1/n1, /d1/r1/n1)=0(同一節點上的程式)

Distance(/d1/r1/n1, /d1/r1/n2)=2(同一機架上的不同節點)

Distance(/d1/r1/n1, /d1/r3/n2)=4(同一資料中心不同機架上的節點)

Distance(/d1/r1/n1, /d2/r4/n2)=6(不同資料中心的節點)

機架

7.2 機架感知(副本節點選擇)

1)低版本Hadoop副本節點選擇

第一個副本在client所處的節點上。如果客戶端在叢集外,隨機選一個。

第二個副本和第一個副本位於不相同機架的隨機節點上。

第三個副本和第二個副本位於相同機架,節點隨機。

機架感知

  1. Hadoop2.7.2 副本節點選擇

第一個副本在client所處的節點上。如果客戶端在叢集外,隨機選一個。

第二個副本和第一個副本位於相同機架,隨機節點。

第三個副本位於不同機架,隨機節點。

機架感知

8.HDFS 檔案讀取過程(非常重要)

HDFS 檔案讀取過程

  1. Client向NameNode發起RPC請求,來確定請求檔案block所在的位置;

  2. NameNode會視情況返回檔案的部分或者全部block列表,對於每個block,NameNode 都會返回含有該 block 副本的 DataNode 地址; 這些返回的 DN 地址,會按照叢集拓撲結構得出 DataNode 與客戶端的距離,然後進行排序,排序兩個規則:網路拓撲結構中距離 Client 近的排靠前;心跳機制中超時彙報的 DN 狀態為 STALE,這樣的排靠後;

  3. Client 選取排序靠前的 DataNode 來讀取 block,如果客戶端本身就是DataNode,那麼將從本地直接獲取資料(短路讀取特性);

  4. 底層上本質是建立 Socket Stream(FSDataInputStream),重複的呼叫父類 DataInputStream 的 read 方法,直到這個塊上的資料讀取完畢;

  5. 當讀完列表的 block 後,若檔案讀取還沒有結束,客戶端會繼續向NameNode 獲取下一批的 block 列表;

  6. 讀取完一個 block 都會進行 checksum 驗證,如果讀取 DataNode 時出現錯誤,客戶端會通知 NameNode,然後再從下一個擁有該 block 副本的DataNode 繼續讀。

  7. read 方法是並行的讀取 block 資訊,不是一塊一塊的讀取;NameNode 只是返回Client請求包含塊的DataNode地址,並不是返回請求塊的資料;

  8. 最終讀取來所有的 block 會合併成一個完整的最終檔案。

從 HDFS 檔案讀寫過程中,可以看出,HDFS 檔案寫入時是序列寫入的,資料包先傳送給節點A,然後節點A傳送給B,B在給C;而HDFS檔案讀取是並行的, 客戶端 Client 直接並行讀取block所在的節點。

9. NameNode 工作機制以及後設資料管理(重要)

NameNode 工作機制

9.1 namenode 與 datanode 啟動

  • namenode工作機制
  1. 第一次啟動namenode格式化後,建立fsimage和edits檔案。如果不是第一次啟動,直接載入編輯日誌和映象檔案到記憶體。
  2. 客戶端對後設資料進行增刪改的請求。
  3. namenode記錄操作日誌,更新滾動日誌。
  4. namenode在記憶體中對資料進行增刪改查。
  • secondary namenode
  1. secondary namenode詢問 namenode 是否需要 checkpoint。直接帶回 namenode 是否檢查結果。
  2. secondary namenode 請求執行 checkpoint。
  3. namenode 滾動正在寫的edits日誌。
  4. 將滾動前的編輯日誌和映象檔案拷貝到 secondary namenode。
  5. secondary namenode 載入編輯日誌和映象檔案到記憶體,併合並。
  6. 生成新的映象檔案 fsimage.chkpoint。
  7. 拷貝 fsimage.chkpoint 到 namenode。
  8. namenode將 fsimage.chkpoint 重新命名成fsimage。

9.2 FSImage與edits詳解

所有的後設資料資訊都儲存在了FsImage與Eidts檔案當中,這兩個檔案就記錄了所有的資料的後設資料資訊,後設資料資訊的儲存目錄配置在了 hdfs-site.xml 當中

		<!--fsimage檔案儲存的路徑-->
		<property>
                <name>dfs.namenode.name.dir</name>
                <value>file:///opt/hadoop-2.6.0-cdh5.14.0/hadoopDatas/namenodeDatas</value>
        </property>
        <!-- edits檔案儲存的路徑 -->
		<property>
                <name>dfs.namenode.edits.dir</name>
                <value>file:///opt/hadoop-2.6.0-cdh5.14.0/hadoopDatas/dfs/nn/edits</value>
  		</property>

客戶端對hdfs進行寫檔案時會首先被記錄在edits檔案中。

edits修改時後設資料也會更新。

每次hdfs更新時edits先更新後客戶端才會看到最新資訊。

fsimage:是namenode中關於後設資料的映象,一般稱為檢查點。

一般開始時對namenode的操作都放在edits中,為什麼不放在fsimage中呢?

因為fsimage是namenode的完整的映象,內容很大,如果每次都載入到記憶體的話生成樹狀拓撲結構,這是非常耗記憶體和CPU。

fsimage內容包含了namenode管理下的所有datanode中檔案及檔案block及block所在的datanode的後設資料資訊。隨著edits內容增大,就需要在一定時間點和fsimage合併。

9.3 FSimage檔案當中的檔案資訊檢視

  • 使用命令 hdfs oiv
cd  /opt/hadoop-2.6.0-cdh5.14.0/hadoopDatas/namenodeDatas/current
hdfs oiv -i fsimage_0000000000000000112 -p XML -o hello.xml

9.4 edits當中的檔案資訊檢視

  • 檢視命令 hdfs oev
cd  /opt/hadoop-2.6.0-cdh5.14.0/hadoopDatas/dfs/nn/edits
hdfs oev -i  edits_0000000000000000112-0000000000000000113 -o myedit.xml -p XML

9.5 secondarynameNode如何輔助管理FSImage與Edits檔案

  1. secnonaryNN通知NameNode切換editlog。
  2. secondaryNN從NameNode中獲得FSImage和editlog(通過http方式)。
  3. secondaryNN將FSImage載入記憶體,然後開始合併editlog,合併之後成為新的fsimage。
  4. secondaryNN將新的fsimage發回給NameNode。
  5. NameNode用新的fsimage替換舊的fsimage。

完成合並的是 secondarynamenode,會請求namenode停止使用edits,暫時將新寫操作放入一個新的檔案中(edits.new)。

secondarynamenode從namenode中通過http get獲得edits,因為要和fsimage合併,所以也是通過http get 的方式把fsimage載入到記憶體,然後逐一執行具體對檔案系統的操作,與fsimage合併,生成新的fsimage,然後把fsimage傳送給namenode,通過http post的方式

namenode從secondarynamenode獲得了fsimage後會把原有的fsimage替換為新的fsimage,把edits.new變成edits。同時會更新fsimage。

hadoop進入安全模式時需要管理員使用dfsadmin的save namespace來建立新的檢查點。

secondarynamenode在合併edits和fsimage時需要消耗的記憶體和namenode差不多,所以一般把namenode和secondarynamenode放在不同的機器上。

fsimage與edits的合併時機取決於兩個引數,第一個引數是預設1小時fsimage與edits合併一次。

  • 第一個引數:時間達到一個小時fsimage與edits就會進行合併
dfs.namenode.checkpoint.period     3600
  • 第二個引數:hdfs操作達到1000000次也會進行合併
dfs.namenode.checkpoint.txns       1000000
  • 第三個引數:每隔多長時間檢查一次hdfs的操作次數
dfs.namenode.checkpoint.check.period   60

9.6 namenode後設資料資訊多目錄配置

為了保證後設資料的安全性,我們一般都是先確定好我們的磁碟掛載目錄,將後設資料的磁碟做RAID1

namenode的本地目錄可以配置成多個,且每個目錄存放內容相同,增加了可靠性。

  • 具體配置方案:

    hdfs-site.xml

	<property>
         <name>dfs.namenode.name.dir</name>
         <value>file:///export/servers/hadoop-2.6.0-cdh5.14.0/hadoopDatas/namenodeDatas</value>
    </property>

9.7 namenode故障恢復

在我們的secondaryNamenode對namenode當中的fsimage和edits進行合併的時候,每次都會先將namenode的fsimage與edits檔案拷貝一份過來,所以fsimage與edits檔案在secondarNamendoe當中也會儲存有一份,如果namenode的fsimage與edits檔案損壞,那麼我們可以將secondaryNamenode當中的fsimage與edits拷貝過去給namenode繼續使用,只不過有可能會丟失一部分資料。這裡涉及到幾個配置選項

  • namenode儲存fsimage的配置路徑
<!--  namenode後設資料儲存路徑,實際工作當中一般使用SSD固態硬碟,並使用多個固態硬碟隔開,冗餘後設資料 -->
	<property>
		<name>dfs.namenode.name.dir</name>
		<value>file:///export/servers/hadoop-2.6.0-cdh5.14.0/hadoopDatas/namenodeDatas</value>
	</property>
  • namenode儲存edits檔案的配置路徑
<property>
		<name>dfs.namenode.edits.dir</name>
		<value>file:///export/servers/hadoop-2.6.0-cdh5.14.0/hadoopDatas/dfs/nn/edits</value>
</property>
  • secondaryNamenode儲存fsimage檔案的配置路徑
<property>
		<name>dfs.namenode.checkpoint.dir</name>
		<value>file:///export/servers/hadoop-2.6.0-cdh5.14.0/hadoopDatas/dfs/snn/name</value>
</property>
  • secondaryNamenode儲存edits檔案的配置路徑
<property>
		<name>dfs.namenode.checkpoint.edits.dir</name>
		<value>file:///export/servers/hadoop-2.6.0-cdh5.14.0/hadoopDatas/dfs/nn/snn/edits</value>
</property>

接下來我們來模擬namenode的故障恢復功能

  1. 殺死namenode程式: 使用jps檢視namenode的程式號 , kill -9 直接殺死。
  2. 刪除namenode的fsimage檔案和edits檔案。

根據上述配置, 找到namenode放置fsimage和edits路徑. 直接全部rm -rf 刪除。

  1. 拷貝secondaryNamenode的fsimage與edits檔案到namenode的fsimage與edits資料夾下面去。

根據上述配置, 找到secondaryNamenode的fsimage和edits路徑, 將內容 使用cp -r 全部複製到namenode對應的目錄下即可。

  1. 重新啟動namenode, 觀察資料是否存在。

10 datanode工作機制以及資料儲存

  • datanode工作機制
  1. 一個資料塊在datanode上以檔案形式儲存在磁碟上,包括兩個檔案,一個是資料本身,一個是後設資料包括資料塊的長度,塊資料的校驗和,以及時間戳。

  2. DataNode啟動後向namenode註冊,通過後,週期性(1小時)的向namenode上報所有的塊資訊。(dfs.blockreport.intervalMsec)。

  3. 心跳是每3秒一次,心跳返回結果帶有namenode給該datanode的命令如複製塊資料到另一臺機器,或刪除某個資料塊。如果超過10分鐘沒有收到某個datanode的心跳,則認為該節點不可用。

  4. 叢集執行中可以安全加入和退出一些機器。

  • 資料完整性
  1. 當DataNode讀取block的時候,它會計算checksum。
  2. 如果計算後的checksum,與block建立時值不一樣,說明block已經損壞。
  3. client讀取其他DataNode上的block。
  4. datanode在其檔案建立後周期驗證checksum。
  • 掉線時限引數設定

datanode程式死亡或者網路故障造成datanode無法與namenode通訊,namenode不會立即把該節點判定為死亡,要經過一段時間,這段時間暫稱作超時時長。HDFS預設的超時時長為10分鐘+30秒。如果定義超時時間為timeout,則超時時長的計算公式為:

timeout = 2 * dfs.namenode.heartbeat.recheck-interval + 10 * dfs.heartbeat.interval。

而預設的dfs.namenode.heartbeat.recheck-interval 大小為5分鐘,dfs.heartbeat.interval預設為3秒。

需要注意的是hdfs-site.xml 配置檔案中的heartbeat.recheck.interval的單位為毫秒dfs.heartbeat.interval的單位為秒

<property>
    <name>dfs.namenode.heartbeat.recheck-interval</name>
    <value>300000</value>
</property>
<property>
    <name>dfs.heartbeat.interval </name>
    <value>3</value>
</property>
  • DataNode的目錄結構

    和namenode不同的是,datanode的儲存目錄是初始階段自動建立的,不需要額外格式化。

在/opt/hadoop-2.6.0-cdh5.14.0/hadoopDatas/datanodeDatas/current這個目錄下檢視版本號

    cat VERSION 
    
    #Thu Mar 14 07:58:46 CST 2019
    storageID=DS-47bcc6d5-c9b7-4c88-9cc8-6154b8a2bf39
    clusterID=CID-dac2e9fa-65d2-4963-a7b5-bb4d0280d3f4
    cTime=0
    datanodeUuid=c44514a0-9ed6-4642-b3a8-5af79f03d7a4
    storageType=DATA_NODE
    layoutVersion=-56

具體解釋:

storageID:儲存id號。

clusterID叢集id,全域性唯一。

cTime屬性標記了datanode儲存系統的建立時間,對於剛剛格式化的儲存系統,這個屬性為0;但是在檔案系統升級之後,該值會更新到新的時間戳。

datanodeUuid:datanode的唯一識別碼。

storageType:儲存型別。

layoutVersion是一個負整數。通常只有HDFS增加新特性時才會更新這個版本號。

  • datanode多目錄配置

datanode也可以配置成多個目錄,每個目錄儲存的資料不一樣。即:資料不是副本。具體配置如下:
- 只需要在value中使用逗號分隔出多個儲存目錄即可

  cd /opt/hadoop-2.6.0-cdh5.14.0/etc/hadoop
  <!--  定義dataNode資料儲存的節點位置,實際工作中,一般先確定磁碟的掛載目錄,然後多個目錄用,進行分割  -->
          <property>
                  <name>dfs.datanode.data.dir</name>
                  <value>file:///opt/hadoop-2.6.0-cdh5.14.0/hadoopDatas/datanodeDatas</value>
          </property>

10.1 服役新資料節點

需求說明:

隨著公司業務的增長,資料量越來越大,原有的資料節點的容量已經不能滿足儲存資料的需求,需要在原有叢集基礎上動態新增新的資料節點。

10.1.1 環境準備

  1. 複製一臺新的虛擬機器出來

將我們純淨的虛擬機器複製一臺出來,作為我們新的節點

  1. 修改mac地址以及IP地址
修改mac地址命令
	vim /etc/udev/rules.d/70-persistent-net.rules
修改ip地址命令
	vim /etc/sysconfig/network-scripts/ifcfg-eth0
  1. 關閉防火牆,關閉selinux
關閉防火牆
	service iptables stop
關閉selinux
	vim /etc/selinux/config
  1. 更改主機名
更改主機名命令,將node04主機名更改為node04.hadoop.com
vim /etc/sysconfig/network
  1. 四臺機器更改主機名與IP地址對映
四臺機器都要新增hosts檔案
vim /etc/hosts

192.168.52.100 node01.hadoop.com  node01
192.168.52.110 node02.hadoop.com  node02
192.168.52.120 node03.hadoop.com  node03
192.168.52.130 node04.hadoop.com  node04
  1. node04伺服器關機重啟
node04執行以下命令關機重啟
	reboot -h now
  1. node04安裝jdk
node04統一兩個路徑
	mkdir -p /export/softwares/
	mkdir -p /export/servers/

然後解壓jdk安裝包,配置環境變數

  1. 解壓hadoop安裝包
在node04伺服器上面解壓hadoop安裝包到/export/servers , node01執行以下命令將hadoop安裝包拷貝到node04伺服器
	cd /export/softwares/
	scp hadoop-2.6.0-cdh5.14.0-自己編譯後的版本.tar.gz node04:$PWD

node04解壓安裝包
	tar -zxf hadoop-2.6.0-cdh5.14.0-自己編譯後的版本.tar.gz -C /export/servers/
  1. 將node01關於hadoop的配置檔案全部拷貝到node04
node01執行以下命令,將hadoop的配置檔案全部拷貝到node04伺服器上面
	cd /export/servers/hadoop-2.6.0-cdh5.14.0/etc/hadoop/
	scp ./* node04:$PWD

10.1.2 服役新節點具體步驟

  1. 建立dfs.hosts檔案
在node01也就是namenode所在的機器的/export/servers/hadoop-2.6.0-cdh5.14.0/etc/hadoop目錄下建立dfs.hosts檔案

[root@node01 hadoop]# cd /export/servers/hadoop-2.6.0-cdh5.14.0/etc/hadoop
[root@node01 hadoop]# touch dfs.hosts
[root@node01 hadoop]# vim dfs.hosts

新增如下主機名稱(包含新服役的節點)
node01
node02
node03
node04
  1. node01編輯hdfs-site.xml新增以下配置

在namenode的hdfs-site.xml配置檔案中增加dfs.hosts屬性

node01執行以下命令 :

cd /export/servers/hadoop-2.6.0-cdh5.14.0/etc/hadoop
vim hdfs-site.xml

# 新增一下內容
	<property>
         <name>dfs.hosts</name>
         <value>/export/servers/hadoop-2.6.0-cdh5.14.0/etc/hadoop/dfs.hosts</value>
    </property>
    <!--動態上下線配置: 如果配置檔案中有, 就不需要配置-->
    <property>
		<name>dfs.hosts</name>
		<value>/export/servers/hadoop-2.6.0-cdh5.14.0/etc/hadoop/accept_host</value>
	</property>
	
	<property>
		<name>dfs.hosts.exclude</name>
		<value>/export/servers/hadoop-2.6.0-cdh5.14.0/etc/hadoop/deny_host</value>
	</property>
  1. 重新整理namenode
  • node01執行以下命令重新整理namenode
[root@node01 hadoop]# hdfs dfsadmin -refreshNodes
Refresh nodes successful
  1. 更新resourceManager節點
  • node01執行以下命令重新整理resourceManager
[root@node01 hadoop]# yarn rmadmin -refreshNodes
19/03/16 11:19:47 INFO client.RMProxy: Connecting to ResourceManager at node01/192.168.52.100:8033
  1. namenode的slaves檔案增加新服務節點主機名稱

node01編輯slaves檔案,並新增新增節點的主機,更改完後,slaves檔案不需要分發到其他機器上面去

node01執行以下命令編輯slaves檔案 :
	cd /export/servers/hadoop-2.6.0-cdh5.14.0/etc/hadoop
	vim slaves
	
新增一下內容: 	
node01
node02
node03
node04
  1. 單獨啟動新增節點
node04伺服器執行以下命令,啟動datanode和nodemanager : 
	cd /export/servers/hadoop-2.6.0-cdh5.14.0/
	sbin/hadoop-daemon.sh start datanode
	sbin/yarn-daemon.sh start nodemanager
  1. 使用負載均衡命令,讓資料均勻負載所有機器
node01執行以下命令 : 
	cd /export/servers/hadoop-2.6.0-cdh5.14.0/
	sbin/start-balancer.sh

10.2 退役舊資料

  1. 建立dfs.hosts.exclude配置檔案

在namenod所在伺服器的/export/servers/hadoop-2.6.0-cdh5.14.0/etc/hadoop目錄下建立dfs.hosts.exclude檔案,並新增需要退役的主機名稱

node01執行以下命令 : 
	cd /export/servers/hadoop-2.6.0-cdh5.14.0/etc/hadoop
	touch dfs.hosts.exclude
	vim dfs.hosts.exclude
新增以下內容:
	node04.hadoop.com

特別注意:該檔案當中一定要寫真正的主機名或者ip地址都行,不能寫node04
  1. 編輯namenode所在機器的hdfs-site.xml

編輯namenode所在的機器的hdfs-site.xml配置檔案,新增以下配置

cd /export/servers/hadoop-2.6.0-cdh5.14.0/etc/hadoop
vim hdfs-site.xml

#新增一下內容:
	<property>
         <name>dfs.hosts.exclude</name>
         <value>/export/servers/hadoop-2.6.0-cdh5.14.0/etc/hadoop/dfs.hosts.exclude</value>
   </property>
  1. 重新整理namenode,重新整理resourceManager
在namenode所在的機器執行以下命令,重新整理namenode,重新整理resourceManager : 

hdfs dfsadmin -refreshNodes
yarn rmadmin -refreshNodes
  1. 節點退役完成,停止該節點程式

等待退役節點狀態為decommissioned(所有塊已經複製完成),停止該節點及節點資源管理器。注意:如果副本數是3,服役的節點小於等於3,是不能退役成功的,需要修改副本數後才能退役。

node04執行以下命令,停止該節點程式 : 
	cd /export/servers/hadoop-2.6.0-cdh5.14.0
	sbin/hadoop-daemon.sh stop datanode
	sbin/yarn-daemon.sh stop nodemanager
  1. 從include檔案中刪除退役節點
namenode所在節點也就是node01執行以下命令刪除退役節點 :
	cd /export/servers/hadoop-2.6.0-cdh5.14.0/etc/hadoop
	vim dfs.hosts
	
刪除後的內容: 刪除了node04
node01
node02
node03
  1. node01執行一下命令重新整理namenode,重新整理resourceManager
hdfs dfsadmin -refreshNodes
yarn rmadmin -refreshNodes
  1. 從namenode的slave檔案中刪除退役節點
namenode所在機器也就是node01執行以下命令從slaves檔案中刪除退役節點 : 
	cd /export/servers/hadoop-2.6.0-cdh5.14.0/etc/hadoop
	vim slaves
刪除後的內容: 刪除了 node04 
node01
node02
node03
  1. 如果資料負載不均衡,執行以下命令進行均衡負載
node01執行以下命令進行均衡負載
	cd /export/servers/hadoop-2.6.0-cdh5.14.0/
	sbin/start-balancer.sh

11 block塊手動拼接成為完整資料

所有的資料都是以一個個的block塊儲存的,只要我們能夠將檔案的所有block塊全部找出來,拼接到一起,又會成為一個完整的檔案,接下來我們就來通過命令將檔案進行拼接:

  1. 上傳一個大於128M的檔案到hdfs上面去

我們選擇一個大於128M的檔案上傳到hdfs上面去,只有一個大於128M的檔案才會有多個block塊。

這裡我們選擇將我們的jdk安裝包上傳到hdfs上面去。

node01執行以下命令上傳jdk安裝包

cd /export/softwares/
hdfs dfs -put jdk-8u141-linux-x64.tar.gz  /
  1. web瀏覽器介面檢視jdk的兩個block塊id

這裡我們看到兩個block塊id分別為

1073742699和1073742700

那麼我們就可以通過blockid將我們兩個block塊進行手動拼接了。

  1. 根據我們的配置檔案找到block塊所在的路徑
根據我們hdfs-site.xml的配置,找到datanode所在的路徑
<!--  定義dataNode資料儲存的節點位置,實際工作中,一般先確定磁碟的掛載目錄,然後多個目錄用,進行分割  -->
        <property>
                <name>dfs.datanode.data.dir</name>
                <value>file:///export/servers/hadoop-2.6.0-cdh5.14.0/hadoopDatas/datanodeDatas</value>
        </property>
        
        
進入到以下路徑 : 此基礎路徑為 上述配置中value的路徑
cd /export/servers/hadoop-2.6.0-cdh5.14.0/hadoopDatas/datanodeDatas/current/BP-557466926-192.168.52.100-1549868683602/current/finalized/subdir0/subdir3
    1. 執行block塊的拼接
將不同的各個block塊按照順序進行拼接起來,成為一個完整的檔案
cat blk_1073742699 >> jdk8u141.tar.gz
cat blk_1073742700 >> jdk8u141.tar.gz
移動我們的jdk到/export路徑,然後進行解壓
mv  jdk8u141.tar.gz /export/
cd /export/
tar -zxf jdk8u141.tar.gz
正常解壓,沒有問題,說明我們的程式按照block塊儲存沒有問題

作者簡介:
園陌,目前就職於一家大而溫馨的網際網路公司,資料開發工程師
公眾號【五分鐘學大資料】的原創作者
本篇文章首發於公眾號,版權歸部落格園與公眾號【五分鐘學大資料】共同所有,轉載請註明本宣告!

相關文章