第十二章 HDFS 各種角色講解

NameNode 和 SecondaryNameNode

NameNode 元數據的管理

WAL(Write ahead Log): 預寫日誌系統

在計算機科學中,預寫式日誌(Write-ahead logging,縮寫 WAL)是關係數據庫系統中 用於提供原子性和持久性(ACID 屬性中的兩個)的一系列技術。在使用 WAL 的系統中,所 有的修改在提交之前都要先寫入 log 文件中。

Log 文件中通常包括 redo 和 undo 信息。這樣做的目的可以通過一個例子來說明。假設 一個程序在執行某些操作的過程中機器掉電了。在重新啟動時,程序可能需要知道當時執行的操作是成功了還是部分成功或者是失敗了。如果使用了 WAL,程序就可以檢查 log 文件, 並對突然掉電時計劃執行的操作內容跟實際上執行的操作內容進行比較。在這個比較的基礎 上,程序就可以決定是撤銷已做的操作還是繼續完成已做的操作,或者是保持原樣。

WAL 允許用 in-place 方式更新數據庫。另一種用來實現原子更新的方法是 shadow paging, 它並不是 in-place 方式。用 in-place 方式做更新的主要優點是減少索引和塊列表的修改。ARIES 是 WAL 系列技術常用的算法。在文件系統中,WAL 通常稱為 journaling。PostgreSQL 也是用 WAL 來提供 point-in-time 恢復和數據庫複製特性。


NN 和 2NN 工作機制

思考:NameNode 中的元數據存儲在哪裡

首先,我們做個假設,如果存儲在 NameNode 節點的磁盤中,因為經常需要進行隨機訪問,還有響應客戶請求,必然是效率過低。因此,元數據需要存放在內存中。但如果只存在內存中,一旦斷電,元數據丟失,整個集群就無法工作了。因此產生在磁盤中備份元數據的 FsImage

這樣又會帶來新的問題,當在內存中的元數據更新時,如果同時更新 FsImage,就會導致效率過低,但如果不更新,就會發生一致性問題,一旦 NameNode 節點斷電,就會產生數據丟失。因此,引入 Edits 文件(只進行追加操作,效率很高)。每當元數據有更新或者添加元數據時,修改內存中的元數據並追加到 Edits 中。這樣,一旦NameNode節 點斷電,可以通過 FsImage 和 Edits 的合併,合成元數據。

但是,如果長時間添加數據到 Edits 中,會導致該文件數據過大,效率降低,而且一旦斷電,恢復元數據需要的時間過長。因此,需要定期進行 FsImage 和 Edits 的合併,如果這個操作由 NameNode 節點完成,又會效率過低。因此,引入一個新的節點 SecondaryNamenode,專門用於 FsImage 和 Edits 的合併

第一階段: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。


NN和2NN工作機制詳解

Fsimage:NameNode 內存中元數據序列化後形成的文件。

Edits:記錄客戶端更新元數據信息的每一步操作(可通過Edits運算出元數據)。

NameNode 啟動時,先滾動 Edits 並生成一個空的 edits.inprogress,然後加載 Edits 和 Fsimage 到內存中,此時 NameNode 內存就持有最新的元數據信息。Client 開始對 NameNode 發送元數據的增刪改的請求,這些請求的操作首先會被記錄到 edits.inprogress 中(查詢元數據的操作不會被記錄在 Edits 中,因為查詢操作不會更改元數據信息),如果此時 NameNode 掛掉,重啟後會從 Edits 中讀取元數據的信息。然後,NameNode 會在內存中執行元數據的增刪改的操作。

由於 Edits 中記錄的操作會越來越多,Edits 文件會越來越大,導致 NameNode 在啟動加載 Edits 時會很慢,所以需要對 Edits 和 Fsimage 進行合併(所謂合併,就是將 Edits 和 Fsimage 加載到內存中,照著 Edits中的操作一步步執行,最終形成新的 Fsimage)。SecondaryNameNode 的作用就是幫助 NameNode 進行Edits 和 Fsimage 的合併工作。

SecondaryNameNode 首先會詢問是否需要(觸發需要滿足兩個條件中的任意一個,定時時間到和中數據寫滿了)。直接帶回是否檢查結果。執行操作,首先會讓滾動並生成一個空的,滾動的目的是給打個標記,以後所有新的操作都寫入,其他未合併的和會拷貝到的本地,然後將拷貝的和加載到內存中進行合併,生成,然後將拷貝給,重命名為後替換掉原來的。在啟動時就只需要加載之前未合併的和即可,因為合併過的中的元數據信息已經被記錄在中。


Fsimage 和 Edits 解析

NameNode 被格式化以後,將在 /opt/module/hadoop-2.7.5/data/tmp/dfs/name/current 目錄中產生如下文件

<code>fsimage_0000000000000000000
fsimage_0000000000000000000.md5
seen_txid
VERSION/<code>

1)Fsimage文件:HDFS 文件系統元數據的一個永久性的檢查點,其中包含 HDFS 文件系統的所有目錄和文件的序列化信息。

2)Edits文件:存放 HDFS 文件系統的所有更新操作的路徑,文件系統客戶端執行的所有寫操作首先會被記錄在 Edits 文件中。

3)seen_txid文件:保存的是一個數字,就是最後一個edits_的數字。

4)每次NameNode啟動的時候都會將Fsimage文件讀入內存,加載Edits文件裡面的更新操作,保證內存中的元數據信息是最新的、同步的,可以看成NameNode啟動的時候就將Fsimage和Edits文件進行了合併。


oiv 查看 Fsimage 文件

(1)查看oiv和oev命令

<code>[bigdata@bigdata101 current]$ hdfs
oiv                 apply the offline fsimage viewer to an fsimage
oev                 apply the offline edits viewer to an edits file/<code>

(2)基本語法

<code>hdfs oiv -p 文件類型 -i鏡像文件 -o 轉換後文件輸出路徑/<code>

(3)案例實操

<code>[bigdata@bigdata101 current]$ hdfs oiv -p XML -i fsimage_0000000000000000085 -o /opt/module/hadoop-2.7.5/fsimage.xml
[bigdata@bigdata101 current]$ cat /opt/module/hadoop-2.7.5/fsimage.xml/<code>

部分顯示結果如下。

<code>    <inode>
     16403
     <type>DIRECTORY/<type>
     <name>input/<name>
     <mtime>1583328317842/<mtime>
     <permission>bigdata:supergroup:rwxr-xr-x/<permission>
     <nsquota>-1/<nsquota>
     <dsquota>-1/<dsquota>
   /<inode>  
   <inode>
     16404
     <type>FILE/<type>
     <name>new_first.txt/<name>
     <replication>2/<replication>
     <mtime>1583327976984/<mtime>
     <atime>1583327976766/<atime>
     <perferredblocksize>134217728/<perferredblocksize>
     <permission>bigdata:supergroup:rw-r--r--/<permission>
     <blocks>
       <block>
         1073741834
         <genstamp>1010/<genstamp>

         <numbytes>12/<numbytes>
       /<block>
     /<blocks>
   /<inode> /<code>

思考:可以看出,Fsimage 中沒有記錄塊所對應 DataNode,為什麼?

在集群啟動後,要求 DataNode 上報數據塊信息,並間隔一段時間後再次上報。


oev查看Edits文件

(1)基本語法

<code>hdfs oev -p 文件類型 -i編輯日誌 -o 轉換後文件輸出路徑/<code>

(2)案例實操

<code>[bigdata@bigdata101 current]$ hdfs oev -p XML -i edits_0000000000000000002-0000000000000000020 -o /opt/module/hadoop-2.7.5/edits.xml
[bigdata@bigdata101 current]$ cat /opt/module/hadoop-2.7.5/edits.xml/<code>

顯示結果如下。

<code>
<edits>
 <edits>-63/<edits>
 <record>
   <opcode>OP_ADD/<opcode>
   <data>
     <txid>6/<txid>
     <length>0/<length>
     <inodeid>16389/<inodeid>
     <path>/user/bigdata/input/wc.input._COPYING_/<path>
     <replication>3/<replication>
     <mtime>1583046446241/<mtime>
     <atime>1583046446241/<atime>

     <blocksize>134217728/<blocksize>
     <client>DFSClient_NONMAPREDUCE_-1929635684_1/<client>
     <client>192.168.24.131/<client>
     <overwrite>true/<overwrite>
     <permission>
       <username>bigdata/<username>
       <groupname>supergroup/<groupname>
       <mode>420/<mode>
     /<permission>
     0de1babf-87ae-41dd-b251-910035b56e20
     3
   /<data>
 /<record>
 <record>
   <opcode>OP_ALLOCATE_BLOCK_ID/<opcode>
   <data>
     <txid>7/<txid>
     <block>1073741825/<block>
   /<data>
 /<record>
 <record>
   <opcode>OP_SET_GENSTAMP_V2/<opcode>
   <data>
     <txid>8/<txid>
     <genstampv2>1001/<genstampv2>
   /<data>
 /<record>
 <record>
   <opcode>OP_ADD_BLOCK/<opcode>
   <data>
     <txid>9/<txid>
     <path>/user/bigdata/input/wc.input._COPYING_/<path>
     <block>
       <block>1073741825/<block>
       0
       <genstamp>1001/<genstamp>
     /<block>
     
     -2
   /<data>
 /<record>

 <record>
   <opcode>OP_CLOSE/<opcode>
   <data>
     <txid>10/<txid>
     <length>0/<length>
     <inodeid>0/<inodeid>
     <path>/user/bigdata/input/wc.input._COPYING_/<path>
     <replication>3/<replication>
     <mtime>1583046447498/<mtime>
     <atime>1583046446241/<atime>
     <blocksize>134217728/<blocksize>
     <client>
     <client>
     <overwrite>false/<overwrite>
     <block>
       <block>1073741825/<block>
       45
       <genstamp>1001/<genstamp>
     /<block>
     <permission>
       <username>bigdata/<username>
       <groupname>supergroup/<groupname>
       <mode>420/<mode>
     /<permission>
   /<data>
 /<record>
/<edits>/<code>

思考:NameNode如何確定下次開機啟動的時候合併哪些Edits?


CheckPoint 時間設置

(1)通常情況下,SecondaryNameNode每隔一小時執行一次。

查看 hadoop-hdfs-2.7.5.jar->hdfs-default.xml

<code><property>
 <name>dfs.namenode.checkpoint.period/<name>
 <value>3600/<value>

 <description>The number of seconds between two periodic checkpoints.
 /<description>
/<property>/<code>

(2)一分鐘檢查一次操作次數,當操作次數達到1百萬時,SecondaryNameNode執行一次。

(3)當操作次數達到1百萬時,SecondaryNameNode執行一次。

<code><property>
 <name>dfs.namenode.checkpoint.check.period/<name>
 <value>60/<value>
 <description>The SecondaryNameNode and CheckpointNode will poll the NameNode
every 'dfs.namenode.checkpoint.check.period' seconds to query the number
of uncheckpointed transactions.
 /<description>
/<property>

<property>
 <name>dfs.namenode.checkpoint.txns/<name>
 <value>1000000/<value>
 <description>The Secondary NameNode or CheckpointNode will create a checkpoint
of the namespace every 'dfs.namenode.checkpoint.txns' transactions, regardless
of whether 'dfs.namenode.checkpoint.period' has expired.
 /<description>
/<property>/<code>


NameNode 故障處理

NameNode故障後,可以採用如下兩種方法恢復數據。

方法一:將SecondaryNameNode中數據拷貝到NameNode存儲數據的目錄

1、kill -9 NameNode進程

2、刪除 NameNode 存儲的數據(/opt/module/hadoop-2.7.5/data/tmp/dfs/name)

<code>[bigdata@bigdata101 name]$ rm -rf /opt/module/hadoop-2.7.5/data/tmp/dfs/name/*/<code>

3、拷貝 SecondaryNameNode 中數據到原 NameNode 存儲數據目錄

<code>[bigdata@bigdata101 dfs]$ scp -r bigdata@bigdata103:/opt/module/hadoop-2.7.5/data/tmp/dfs/namesecondary/* ./name//<code>

4、重新啟動 NameNode

<code>[bigdata@bigdata101 hadoop-2.7.5]$ sbin/hadoop-daemon.sh start namenode/<code>


方法二:使用-importCheckpoint選項啟動NameNode守護進程,從而將SecondaryNameNode中數據拷貝到NameNode目錄中。

1、修改hdfs-site.xml中的

<code><property>
 <name>dfs.namenode.checkpoint.period/<name>
 <value>120/<value>
/<property>

<property>
 <name>dfs.namenode.name.dir/<name>
 <value>/opt/module/hadoop-2.7.5/data/tmp/dfs/name/<value>
/<property>/<code>

2、kill -9 NameNode 進程

3、刪除 NameNode 存儲的數據(/opt/module/hadoop-2.7.5/data/tmp/dfs/name)

<code>[bigdata@bigdata101 hadoop-2.7.5]$ rm -rf /opt/module/hadoop-2.7.5/data/tmp/dfs/name/*/<code>

4、如果 SecondaryNameNode 不和 NameNode 在一個主機節點上,需要將 SecondaryNameNode 存儲數據的目錄拷貝到 NameNode 存儲數據的平級目錄,並刪除 in_use.lock 文件

<code>[bigdata@bigdata101 dfs]$ scp -r bigdata@bigdata103:/opt/module/hadoop-2.7.5/data/tmp/dfs/namesecondary ./
[bigdata@bigdata101 namesecondary]$ rm -rf in_use.lock

[bigdata@bigdata101 dfs]$ pwd
/opt/module/hadoop-2.7.5/data/tmp/dfs
[bigdata@bigdata101 dfs]$ ls
data name namesecondary/<code>

5、導入檢查點數據(等待一會ctrl+c結束掉)

<code>[bigdata@bigdata101 hadoop-2.7.5]$ bin/hdfs namenode -importCheckpoint/<code>

6、啟動 NameNode

<code>[bigdata@bigdata101 hadoop-2.7.5]$ sbin/hadoop-daemon.sh start namenode/<code>


NameNode 多目錄配置

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

2、具體配置如下

(1)在hdfs-site.xml文件中增加如下內容

<code><property>
<name>dfs.namenode.name.dir/<name>
<value>file:///${hadoop.tmp.dir}/dfs/name1,file:///${hadoop.tmp.dir}/dfs/name2
/<value>
/<property>/<code>

(2)停止集群,刪除data和logs中所有數據。

<code>[bigdata@bigdata101 hadoop-2.7.5]$ rm -rf data/ logs/
[bigdata@bigdata102 hadoop-2.7.5]$ rm -rf data/ logs/
[bigdata@bigdata103 hadoop-2.7.5]$ rm -rf data/ logs//<code>

(3)格式化集群並啟動。

<code>[bigdata@bigdata101 hadoop-2.7.5]$  bin/hdfs namenode –format
[bigdata@bigdata101 hadoop-2.7.5]$ sbin/start-dfs.sh/<code>

(4)查看結果

<code>[bigdata@bigdata101 dfs]$ ll
總用量 12
drwx------. 3 bigdata bigdata 4096 3月   5 08:40 data
drwxrwxr-x. 3 bigdata bigdata 4096 3月   5 08:40 name1
drwxrwxr-x. 3 bigdata bigdata 4096 3月   5 08:40 name2/<code>


DataNode


DataNode工作機制


1)一個數據塊在 DataNode 上以文件形式存儲在磁盤上,包括兩個文件,一個是數據本身,一個是元數據包括數據塊的長度,塊數據的校驗和,以及時間戳。

2)DataNode 啟動後向 NameNode 註冊,通過後,週期性(1小時)的向 NameNode 上報所有的塊信息。

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

4)集群運行中可以安全加入和退出一些機器。


數據完整性

思考:如果電腦磁盤裡面存儲的數據是控制高鐵信號燈的紅燈信號(1)和綠燈信號(0),但是存儲該數據的磁盤壞了,一直顯示是綠燈,是否很危險?同理DataNode節點上的數據損壞了,卻沒有發現,是否也很危險,那麼如何解決呢?

如下是 DataNode 節點保證數據完整性的方法。

1)當 DataNode 讀取 Block 的時候,它會計算 CheckSum。

2)如果計算後的 CheckSum,與 Block 創建時值不一樣,說明 Block 已經損壞。

3)Client 讀取其他 DataNode 上的 Block。

4)在其文件創建後周期驗證,如圖所示。

掉線時限參數設置

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

<code><property>
 <name>dfs.namenode.heartbeat.recheck-interval/<name>
 <value>300000/<value>
 <description>

  This time decides the interval to check for expired datanodes.
  With this value and dfs.heartbeat.interval, the interval of
  deciding the datanode is stale or not is also calculated.
  The unit of this configuration is millisecond.
 /<description>
/<property>

<property>
 <name>dfs.heartbeat.interval/<name>
 <value>3/<value>
 <description>Determines datanode heartbeat interval in seconds./<description>
/<property>/<code>


服役新數據節點

0、需求

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

1、環境準備

(1)在 bigdata103 主機上再克隆一臺 bigdata104 主機

(2)修改 IP 地址和主機名稱

(3)刪除原來 HDFS 文件系統留存的文件(/opt/module/hadoop-2.7.2/data和log)

(4)source 一下配置文件

<code>[bigdata@bigdata104 hadoop-2.7.5]$ source /etc/profile/<code>

2、 服役新節點具體步驟

(1)直接啟動 DataNode,即可關聯到集群

<code>[bigdata@bigdata104 hadoop-2.7.5]$ sbin/hadoop-daemon.sh start datanode
[bigdata@bigdata104 hadoop-2.7.5]$ sbin/yarn-daemon.sh start nodemanager/<code>

http://bigdata101:50070/dfshealth.html#tab-overview

(2)在 bigdata104 上上傳文件

<code>[bigdata@bigdata104 hadoop-2.7.5]$ hadoop fs -put /opt/module/hadoop-2.7.5/LICENSE.txt //<code>

(3)如果數據不均衡,可以用命令實現集群的再平衡

<code>[bigdata@bigdata101 sbin]$ ./start-balancer.sh/<code>


退役舊數據節點

添加白名單

添加到白名單的主機節點,都允許訪問 NameNode,不在白名單的主機節點,都會被退出。

配置白名單的具體步驟如下:

(1)在NameNode的 /opt/module/hadoop-2.7.5/etc/hadoop 目錄下創建dfs.hosts文件

<code>[bigdata@bigdata101 hadoop]$ pwd
/opt/module/hadoop-2.7.5/etc/hadoop
[bigdata@bigdata101 hadoop]$ touch dfs.hosts
[bigdata@bigdata101 hadoop]$ vi dfs.hosts/<code>

添加如下主機名稱(不添加 bigdata104)

<code>bigdata101
bigdata102

bigdata103/<code>

(2)在 NameNode 的 hdfs-site.xml 配置文件中增加 dfs.hosts 屬性

<code><property>
<name>dfs.hosts/<name>
<value>/opt/module/hadoop-2.7.5/etc/hadoop/dfs.hosts/<value>
/<property>/<code>

(3)配置文件分發

<code>[bigdata@bigdata101 hadoop]$ xsync hdfs-site.xml/<code>

(4)刷新NameNode

<code>[bigdata@bigdata101 hadoop-2.7.5]$ hdfs dfsadmin -refreshNodes
Refresh nodes successful/<code>

(5)更新ResourceManager節點

<code>[bigdata@bigdata101 hadoop-2.7.5]$ yarn rmadmin -refreshNodes/<code>

(6)在web瀏覽器上查看

http://bigdata101:50070/dfshealth.html#tab-overview

(7)如果數據不均衡,可以用命令實現集群的再平衡

<code>[bigdata@bigdata101 sbin]$ ./start-balancer.sh/<code>


黑名單退役

在黑名單上面的主機都會被強制退出。

1、在 NameNode 的 /opt/module/hadoop-2.7.7/etc/hadoop 目錄下創建 dfs.hosts.exclude 文件

<code>[bigdata@bigdata101 hadoop]$ pwd
/opt/module/hadoop-2.7.5/etc/hadoop

[bigdata@bigdata101 hadoop]$ touch dfs.hosts.exclude
[bigdata@bigdata101 hadoop]$ vi dfs.hosts.exclude/<code>

添加如下主機名稱(要退役的節點)

bigdata104

2.在NameNode的hdfs-site.xml配置文件中增加dfs.hosts.exclude屬性

<code><property>
<name>dfs.hosts.exclude/<name>
<value>/opt/module/hadoop-2.7.5/etc/hadoop/dfs.hosts.exclude/<value>
/<property>/<code>

3.刷新NameNode、刷新ResourceManager

<code>[bigdata@bigdata101 hadoop-2.7.5]$ hdfs dfsadmin -refreshNodes
Refresh nodes successful
[bigdata@bigdata101 hadoop-2.7.5]$ yarn rmadmin -refreshNodes/<code>

4、檢查Web瀏覽器,退役節點的狀態為decommission in progress(退役中),說明數據節點正在複製塊到其他節點。

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


圖3-18 已退役

<code>[bigdata@bigdata104 hadoop-2.7.5]$ sbin/hadoop-daemon.sh stop datanode
stopping datanode
[bigdata@bigdata104 hadoop-2.7.5]$ sbin/yarn-daemon.sh stop nodemanager
stopping nodemanager/<code>

\\6. 如果數據不均衡,可以用命令實現集群的再平衡

<code>[bigdata@bigdata101 hadoop-2.7.5]$ sbin/start-balancer.sh /<code>

注意:不允許白名單和黑名單中同時出現同一個主機名稱。


DataNode多目錄配置

1、DataNode也可以配置成多個目錄,每個目錄存儲的數據不一樣。即:數據不是副本

2、具體配置如下

hdfs-site.xml

<code><property>
<name>dfs.datanode.data.dir/<name>
<value>file:///${hadoop.tmp.dir}/dfs/data1,file:///${hadoop.tmp.dir}/dfs/data2
/<value>
/<property>/<code>



分享到:


相關文章: