http://blog.sina.com.cn/s/blog_7c5a82970101szjp.html
hadoop集群崩潰恢復記錄
一.崩潰原因
搭建的是一個hadoop測試集群,所以將數據備份參數設置為dfs.replication=1,這樣如果有一台datanode損壞的話,數據就會失去。但不幸的是,剛好就有一台機器由於負載過高,導致數據操壞。進而后面需要重啟整個hadoop集群,重啟后啟動namenode啟動不了。報如下錯誤:
- FSNamesystem initialization failed saveLeases found path /tmp/xxx/aaa.txt but no matching entry in namespace.
FSNamesystem initialization failed saveLeases found path /tmp/xxx/aaa.txt but no matching entry in namespace.
二.修復namenode
hadoop 集群崩潰了. 導致namenode啟動不了.
1. 刪除 namenode主節點的metadata配置目錄
rm -fr /data/hadoop-tmp/hadoop-hadoop/dfs/name
2. 啟動secondnamenode
使用start-all.sh命令啟動secondnamenode,namenode的啟動不了不管
3. 從secondnamenode恢復
使用命令: hadoop namenode -importCheckpoint
恢復過程中,發現數據文件有些已經損壞(因為dfs.replication=1),所以一直無法退出安全模式(safemode),一直報如下提示:
- The ratio of reported blocks 0.8866 has not reached the threshold 0.9990 . Safe mode will be turned off automatically.
The ratio of reported blocks 0.8866 has not reached the threshold 0.9990. Safe mode will be turned off automatically.
4.強制退出safemode
- hadoop dfsadmin -safemode leave
hadoop dfsadmin -safemode leave
最后啟動成功,查看hdfs網頁報警告信息:
- WARNING : There are about 257 missing blocks. Please check the log or run fsck.
WARNING : There are about 257 missing blocks. Please check the log or run fsck.
5.檢查損壞的hdfs文件列表
使用命令可以打印出損壞的文件列表:
- ./hadoop fsck /
./hadoop fsck /
打印結果:
- /user/hive/warehouse/pay_consume_orgi/dt= 2011 - 06 - 28 /consume_2011- 06 - 28 .sql: MISSING 1 blocks of total size 1250990 B..
- /user/hive/warehouse/pay_consume_orgi/dt= 2011 - 06 - 29 /consume_2011- 06 - 29 .sql: CORRUPT block blk_977550919055291594
- /user/hive/warehouse/pay_consume_orgi/dt= 2011 - 06 - 29 /consume_2011- 06 - 29 .sql: MISSING 1 blocks of total size 1307147 B..................Status: CORRUPT
- Total size: 235982871209 B
- Total dirs: 1213
- Total files: 1422
- Total blocks (validated): 4550 (avg. block size 51864367 B)
- ********************************
- CORRUPT FILES: 277
- MISSING BLOCKS: 509
- MISSING SIZE: 21857003415 B
- CORRUPT BLOCKS: 509
- ********************************
/user/hive/warehouse/pay_consume_orgi/dt=2011-06-28/consume_2011-06-28.sql: MISSING 1 blocks of total size 1250990 B.. /user/hive/warehouse/pay_consume_orgi/dt=2011-06-29/consume_2011-06-29.sql: CORRUPT block blk_977550919055291594 /user/hive/warehouse/pay_consume_orgi/dt=2011-06-29/consume_2011-06-29.sql: MISSING 1 blocks of total size 1307147 B..................Status: CORRUPT Total size: 235982871209 B Total dirs: 1213 Total files: 1422 Total blocks (validated): 4550 (avg. block size 51864367 B) ******************************** CORRUPT FILES: 277 MISSING BLOCKS: 509 MISSING SIZE: 21857003415 B CORRUPT BLOCKS: 509 ********************************
沒有冗余備份,只能刪除損壞的文件,使用命令:
- ./hadoop fsck --delete
./hadoop fsck --delete
三.總結
一定需要將你的secondnamenode及namenode分開在不同兩台機器運行,增加namenode的容錯性。以便在集群崩潰時可以從secondnamenode恢復數據.
1.修改conf/core-site.xml ,增加
- <</span> property >
- <</span> name > fs.checkpoint.period </</span> name >
- <</span> value > 3600 </</span> value >
- <</span> description > The number of seconds between two periodic checkpoints. </</span> description >
- </</span> property >
- <</span> property >
- <</span> name > fs.checkpoint.size </</span> name >
- <</span> value > 67108864 </</span> value >
- <</span> description > The size of the current edit log (in bytes) that triggers a periodic checkpoint even if the fs.checkpoint.period hasn't expired. </</span> description >
- </</span> property >
- <</span> property >
- <</span> name > fs.checkpoint.dir </</span> name >
- <</span> value > /data/work/hdfs/namesecondary </</span> value >
- <</span> description > Determines where on the local filesystem the DFS secondary name node should store the temporary images to merge. If this is a comma-delimited list of directories then the image is replicated in all of the directories for redundancy. </</span> description >
- </</span> property >
fs.checkpoint.period表示多長時間記錄一次hdfs的鏡像。默認是1小時。
fs.checkpoint.size表示一次記錄多大的size,默認64M
2.修改conf/hdfs-site.xml ,增加
- <</span> property >
- <</span> name > dfs.http.address </</span> name >
- <</span> value > master:50070 </</span> value >
- <</span> description > The address and the base port where the dfs namenode web ui will listen on. If the port is 0 then the server will start on a free port. </</span> description >
- </</span> property >
0.0.0.0改為namenode的IP地址
3.重啟hadoop,然后檢查是否啟動是否成功。
登錄secondarynamenode所在的機器,輸入jps查看secondarynamenode進程
進入secondarynamenode的目錄/data/work/hdfs/namesecondary
正確的結果:
如果沒有,請耐心等待,只有到了設置的checkpoint的時間或者大小,才會生成。
4.恢復
制造namenode宕機的情況
1) kill 掉namenode的進程
- [root @master name]# jps
- 11749 NameNode
- 12339 Jps
- 11905 JobTracker
- [root@master name]# kill 11749
2)刪除dfs.name.dir所指向的文件夾,這里是/data/work/hdfs/name
- [root @master name]# rm -rf *
刪除name目錄下的所有內容,但是必須保證name這個目錄是存在的
3)從secondarynamenode遠程拷貝namesecondary文件到namenode的namesecondary
- [root @master hdfs]# scp -r slave- 001 :/data/work/hdfs/namesecondary/ ./
4)啟動namenode
- [root @master /data]# hadoop namenode –importCheckpoint
正常啟動以后,屏幕上會顯示很多log,這個時候namenode就可以正常訪問了
5)檢查
使用hadoop fsck /user命令檢查文件Block的完整性
6)停止namenode,使用crrl+C或者會話結束
7)刪除namesecondary目錄下的文件(保存干凈)
- [root @master namesecondary]# rm -rf *
8)正式啟動namenode
- [root @master bin]# ./hadoop-daemon.sh start namenode
恢復工作完成,檢查hdfs的數據
balancer
在使用start-balancer.sh時,
默認使用1M/S(1048576)的速度移動數據(so slowly...)
修改hdfs-site.xml配置,這里我們使用的是20m/S
dfs.balance.bandwidthPerSec
20971520
Specifies the maximum bandwidth that each datanode can utilize for the balancing purpose in term of the number of bytes per second.
然后結果是導致job運行變得不穩定,出現一些意外的長map單元,某些reduce時間處理變長(整個集群負載滿滿的情況下,外加20m/s的balance),據說淘寶的為10m/s,需要調整后實驗,看看情況如何。
- hadoop balancer -threshold 5
安全模式
有兩個方法離開這種安全模式:
(1)修改dfs.safemode.threshold.pct為一個比較小的值,缺省是0.999。
dfs.safemode.threshold.pct(缺省值0.999f)
HDFS啟動的時候,如果DataNode上報的block個數達到了元數據記錄的block個數的0.999倍才可以離開安全模式,否則一直是這種只讀模式。如果設為1則HDFS永遠是處於SafeMode。
(2)hadoop dfsadmin -safemode leave命令強制離開
dfsadmin -safemode value 參數value的說明:
enter - 進入安全模式
leave - 強制NameNode離開安全模式
get - 返回安全模式是否開啟的信息
wait - 等待,一直到安全模式結束。
一、dits和fsimage
首先要提到兩個文件edits和fsimage,下面來說說他們是做什么的。
- 集群中的名稱節點(NameNode)會把文件系統的變化以追加保存到日志文件edits中。
- 當名稱節點(NameNode)啟動時,會從鏡像文件 fsimage 中讀取HDFS的狀態,並且把edits文件中記錄的操作應用到fsimage,也就是合並到fsimage中去。合並后更新fsimage的HDFS狀態,創建一個新的edits文件來記錄文件系統的變化
那么問題來了,只有在名稱節點(NameNode)啟動的時候才會合並fsimage和edits,那么久而久之edits文件會越來越大,特別是大型繁忙的HDFS集群。這種情況下,由於某種原因你要重啟名稱節點(NameNode),那么會花費很長的時間去合並fsimge和edits,然后HDFS 才能運行。
二、Secondary NameNode
目前使用的版本hadoop-0.20.2可以使用Secondary NameNode來解決上面的問題。Secondary NameNode定期合並fsimage和edits日志,把edits日志文件大小控制在一個限度下。因為內存需求和NameNode差不多(On the same order),所以Sencondary NameNode通常要運行在另外個機器上。
secondary NameNode配置在conf/masters文件,啟動命令:bin/start-dfs.sh(如果你使用不建議的start-all.sh也是會啟動的)。
三、什么時候checkpiont
secondary NameNode 什么時候執行checkpoint來合並fsimage和eidts。呢?有兩個配置參數控制:
- fs.checkpoint.period 指定兩次checkpoint的最大時間間隔,默認3600秒。
- fs.checkpoint.size 規定edits文件的最大值,一旦超過這個值則強制checkpoint,不管是否到達最大時間間隔。默認大小是64M。
secondary NameNode 保存最后一次checkpoint的結果,存儲結構和主節點(NameNode)的一樣,所以主節點(NameNode)可以隨時來讀取。
如果你沒有啟動secondary NameNode 那么可以試試 bin/hadoop secondarynamenode -checkpoint 甚至 bin/hadoop secondarynamenode -checkpoint force. 看看生成的文件。
checkpoint可以解決重啟NameNode時間過長的弊端。另外還有偏方:
四、Import Checkpoint(恢復數據)
如果主節點掛掉了,硬盤數據需要時間恢復或者不能恢復了,現在又想立刻恢復HDFS,這個時候就可以import checkpoint。步驟如下:
- 拿一台和原來機器一樣的機器,包括配置和文件,一般來說最快的是拿你節點機器中的一台,立馬能用(部分配置要改成NameNode的配置)
- 創建一個空的文件夾,該文件夾就是配置文件中dfs.name.dir所指向的文件夾。
- 拷貝你的secondary NameNode checkpoint出來的文件,到某個文件夾,該文件夾為fs.checkpoint.dir指向的文件夾
- 執行命令bin/hadoop namenode -importCheckpoint
這樣NameNode會讀取checkpoint文件,保存到dfs.name.dir。但是如果你的dfs.name.dir包含合法的 fsimage,是會執行失敗的。因為NameNode會檢查fs.checkpoint.dir目錄下鏡像的一致性,但是不會去改動它。
值得推薦的是,你要注意備份你的dfs.name.dir和 ${hadoop.tmp.dir}/dfs/namesecondary。
五、Checkpoint Node 和 Backup Node
在后續版本中hadoop-0.21.0,還提供了另外的方法來做checkpoint:Checkpoint Node 和 Backup Node。則兩種方式要比secondary NameNode好很多。所以 The Secondary NameNode has been deprecated. Instead, consider using the Checkpoint Node or Backup Node.
Checkpoint Node像是secondary NameNode的改進替代版,Backup Node提供更大的便利,這里就不再介紹了。
(1)NameNode的內存中保存了龐大的目錄樹結構,這個結構用來保存文件目錄結構和文件Block之間的映射,這種結構關系會固化在磁盤上,但是對樹的改動頻繁發生,什么時候將樹寫入磁盤呢?把每次操作應用到內存中的樹上,並把操作記錄成日志文件,每次操作不會改變固化在磁盤上的改動發生之前的目錄樹,適當的時候做一次固化操作並記錄時間。
(2)NameNode上面的磁盤目錄結構:
[hadoop@localhost dfs]$ ls -R name
name:
current image in_use.lock
name/current:
edits fsimage fstime VERSION
name/image:
fsimage
in_use.lock的功能和DataNode的一致。fsimage保存的是文件系統的目錄樹,edits則是文件樹上的操作日志,fstime是上一次新打開一個操作日志的時間(long型)。NameNode成功載入一次fsimage就要把這個時刻記錄在fstime中,fstime表示edits第一條記錄開始記錄的時刻。saveImage的時候需要先寫入中間文件,防止中途斷電。
image/ fsimage 是一個保護文件,防止0.13以前的版本啟動(0.13以前版本將fsimage存放在name/image目錄下,如果用0.13版本啟動,顯然在讀fsimage會出錯 J )。也就是說寫入fsimage要有兩份。
(3)管理NameNode磁盤目錄的是FSImage,也是繼承Storage類的,和DataStorage類似,有升級回退機制,暫時不考慮。
(4)FSImage需要支持參數-importCheckpoint,該參數用於在某一個checkpoint目錄里加載HDFS的目錄信息,並更新到當前系統,該參數的主要功能在方法doImportCheckpoint中。該方法很簡單,通過讀取配置的 checkpoint目錄來加載fsimage文件和日志文件,然后利用saveFSImage(下面討論)保存到當前的工作目錄,完成導入。
(5)loadFSImage用來在多個目錄中選擇最新的fsimage和edit來載入,最新以及fsimage和edit的一致性由fstime保證,載入過程中對NameNode崩潰的處理要分析saveFSImage的過程在明白。
(6)saveFSImage()的功能正好相反,它將內存中的目錄樹持久化,很自然,目錄樹持久化后就可以把日志清空。 saveFSImage()會創建edits.new,並把當前內存中的目錄樹持久化到fsimage.ckpt(fsimage現在還存在),然后重新打開日志文件edits和edits.new,這會導致日志文件edits和edits.new被清空。最后,saveFSImage()調用 rollFSImage()方法。
rollFSImage()上來就把所有的edits.new都改為edits(經過了方法saveFSImage,它們都已經為空),然后再把fsimage.ckpt改為fsimage。
(7)saveFSImage和loadFSImage為了考慮NameNode突然崩潰的情況使磁盤固化操作得以回滾創建了中間狀態,中間狀態的描述方式就是在磁盤上建立臨時文件。
(1)NameNode保存的兩種信息:文件與block的映射、block與DataNode的映射。文件和block的映射,固化在磁盤上。而block和DataNode的映射在DataNode啟動時上報給NameNode
(2)DatanodeProtocol:用於DataNode來調用NameNode上的方法,情景是DataNode向NameNode通信,方法參數傳遞到NameNode上;
ClientProtocol:提供給客戶端,用於訪問NameNode。它包含了文件角度上的HDFS功能。和GFS一樣,HDFS不提供 POSIX形式的接口,而是使用了一個私有接口。一般來說,程序員通過org.apache.hadoop.fs.FileSystem來和HDFS打交道,不需要直接使用該接口;
NamenodeProtocol: 用於從 NameNode 到 NameNode 的通信;
InterDatanodeProtocol:用於DataNode和DataNode通信,只有一個updateBlock(Block oldblock, Block newblock, boolean finalize)方法;
ClientDatanodeProtocol:用於Client和DataNode之間通信,只有recoverBlock(Block block, boolean keepLength,
DatanodeInfo[] targets)方法,但是Client和DataNode之間應該不只這些,需要到后面看到讀寫的情況在仔細分析;
(3)INode是一個抽象類,它的兩個字類,分別對應着目錄(INodeDirectory)和文件(INodeFile)。 INodeDirectoryWithQuota,如它的名字隱含的,是帶了容量限制的目錄。INodeFileUnderConstruction,抽象了正在構造的文件,當我們需要在HDFS中創建文件的時候,由於創建過程比較長,目錄系統會維護對應的信息。
INode中的成員變量有:name,目錄/文件名;modificationTime和 accessTime是最后的修改時間和訪問時間;parent指向了父目錄;permission是訪問權限。HDFS采用了和UNIX/Linux類似的訪問控制機制。系統維護了一個類似於UNIX系統的組表(group)和用戶表(user),並給每一個組和用戶一個ID,permission在 INode中是long型,它同時包含了組和用戶信息。
INode中的抽象方法:collectSubtreeBlocksAndClear,用來收集INode 所有孩子的block,因為INode可能是文件或者目錄,目錄的話就不含有Block,而文件則有多個Block,返回值為文件的個數而非Block的個數;computeContentSummary用於遞歸計算INode包含的一些相關信息,如文件數,目錄數,占用磁盤空間。
(4)INodeDirectory是INode的子類,里面有List children,因為目錄下既有目錄也有文件。
(5)INodeDirectoryWithQuota進一步加強了INodeDirectory,限制了INodeDirectory可以使用的空間。
(6)INodeFile是HDFS中的文件,BlockInfo blocks []對應這個文件的列表,BlockInfo增強了Block類。
(7)INodeFileUnderConstruction 保存了正在構造的文件的一些信息,包括clientName,這是目前擁有租約的節點名(創建文件時,只有一個節點擁有租約,其他節點配合這個節點工作)。clientMachine是構造該文件的客戶端名稱,如果構造請求由DataNode發起,clientNode會保持相應的信息,targets保存了配合構造文件的所有節點。租約就是一次操作的許可證,只在一個節點中持有。
(8)BlocksMap:Whose essential functions round aroud Map.This class maintains the map from a block to its metadata. block's metadata currently includes INode it belongs(INodeFile) to and the datanodes that store the block(DatanodeDescriptor). BlockInfo contains INodeFile and DatanodeDescriptor which enhances Block.
(9)NameNode需要知道DataNode的信息,最基本的是DatanodeID(hostname:portNumber,unique per cluster storageID(貌似沒有什么用),infoserver的端口,ipcserver的端口)
(10)再加一些信息變成DatanodeInfo增加了一些動態信息(容量等),再加上一些Block的動態信息變成 DatanodeDescriptor,DatanodeDescriptor包含了兩個BlockQueue,分別記錄了該DataNode上准備復制(replicateBlocks)和Lease恢復(recoverBlocks這個操作有些不明白)的BlockTargetPair(Block和多個目的DataNode的結構)。同時還有一個Block集合,保存的是該DataNode上已經失效的Block。 DatanodeDescriptor提供一系列方法,用於操作上面保存的隊列和集合。也提供get*Command方法,用於生成發送到 DataNode的命令。當NameNode收到DataNode對現在管理的Block狀態的匯報是,會調用reportDiff,找出和現在NameNode上的信息差別,以供后續處理用。
光從字面上來理解,很容易讓一些初學者先入為主的認為:SecondaryNameNode(snn)就是NameNode(nn)的熱備進程。其實不是。snn是HDFS架構中的一個組成部分,但是經常由於名字而被人誤解它真正的用途,其實它真正的用途,是用來保存namenode中對HDFS metadata的信息的備份,並減少namenode重啟的時間。對於hadoop進程中 ,要配置好並正確的使用 snn,還是需要做一些工作的。hadoop的默認配置中讓 snn進程默認運行在了 namenode 的那台機器上,但是這樣的話,如果這台機器出錯,宕機,對恢復HDFS文件系統是很大的災難,更好的方式是:將snn的進程配置在另外一台機器上運行。
在 hadoop中,namenode負責對HDFS的metadata的持久化存儲,並且處理來自客戶端的對HDFS的各種操作的交互反饋。為了保證交互速度,HDFS文件系統的metadata是被load到namenode機器的內存中的,並且會將內存中的這些數據保存到磁盤進行持久化存儲。為了保證這個持久化過程不會成為HDFS操作的瓶頸,hadoop采取的方式是:沒有對任何一次的當前文件系統的snapshot進行持久化,對HDFS最近一段時間的操作list會被保存到namenode中的一個叫Editlog的文件中去。當重啟namenode時,除了 load fsImage以外,還會對這個EditLog文件中記錄的HDFS操作進行replay,以恢復HDFS重啟之前的最終狀態。
而 SecondaryNameNode,會周期性的將EditLog中記錄的對HDFS的操作合並到一個checkpoint中,然后清空 EditLog。所以namenode的重啟就會Load最新的一個checkpoint,並replay EditLog中記錄的hdfs操作,由於EditLog中記錄的是從上一次checkpoint以后到現在的操作列表,所以就會比較小。如果沒有snn的這個周期性的合並過程,那么當每次重啟namenode的時候,就會花費很長的時間。而這樣周期性的合並就能減少重啟的時間。同時也能保證HDFS系統的完整性。
這就是 SecondaryNameNode所做的事情。所以snn並不能分擔namenode上對HDFS交互性操作的壓力。盡管如此,當 namenode機器宕機或者namenode進程出問題時,namenode的daemon進程可以通過人工的方式從snn上拷貝一份metadata 來恢復HDFS文件系統。
至於為什么要將SNN進程運行在一台非NameNode的機器上,這主要出於兩點考慮:
- 可擴展性:創建一個新的HDFS的snapshot需要將namenode中load到內存的metadata信息全部拷貝一遍,這樣的操作需要的內存就需要和namenode占用的內存一樣,由於分配給namenode進程的內存其實是對HDFS文件系統的限制,如果分布式文件系統非常的大,那么 namenode那台機器的內存就可能會被namenode進程全部占據。
- 容錯性:當snn創建一個checkpoint的時候,它會將checkpoint拷貝成metadata的幾個拷貝。將這個操作運行到另外一台機器,還可以提供分布式文件系統的容錯性。
配置將SecondaryNameNode運行在另外一台機器上
HDFS的一次運行實例是通過在namenode機器上的$HADOOP_HOME/bin/start-dfs.sh( 或者start-all.sh )腳本來啟動的。這個腳本會在運行該腳本的機器上啟動 namenode進程,而slaves機器上都會啟動DataNode進程,slave機器的列表保存在 conf/slaves文件中,一行一台機器。並且會在另外一台機器上啟動一個snn進程,這台機器由 conf/masters文件指定。所以,這里需要嚴格注意, conf/masters 文件中指定的機器,並不是說jobtracker或者namenode進程要運行在這台機器上,因為這些進程是運行在 launch bin/start-dfs.sh或者 bin/start-mapred.sh(start-all.sh)的機器上的。所以,masters這個文件名是非常的令人混淆的,應該叫做 secondaries會比較合適。然后,通過以下步驟:
-
- 將所有想要運行secondarynamenode進程的機器寫到masters文件中,一行一台。
- 修改在masters文件中配置了的機器上的conf/hadoop-site.xml文件,加上如下選項:
- dfs.http.address
- namenode.hadoop-host.com:50070
core-site.xml:這里有2個參數可配置,但一般來說我們不做修改。fs.checkpoint.period表示多長時間記錄一次hdfs的鏡像。默認是1小時。fs.checkpoint.size表示一次記錄多大的size,默認64M。
- fs.checkpoint.period
- 3600
- The number of seconds between two periodic checkpoints.
- fs.checkpoint.size
- 67108864
- The size of the current edit log (in bytes) that triggers
- a periodic checkpoint even if the fs.checkpoint.period hasn't expired.
3、配置檢查。配置完成之后,我們需要檢查一下是否成功。我們可以通過查看運行secondarynamenode的機器上文件目錄來確定是否成功配置。首先輸入jps查看是否存在secondarynamenode進程。如果存在,在查看對應的目錄下是否有備份記錄。
該目錄一般存在於hadoop.tmp.dir/dfs/namesecondary/下面。
四、恢復
1、配置完成了,如何恢復。首先我們kill掉namenode進程,然后將hadoop.tmp.dir目錄下的數據刪除掉。制造master掛掉情況。
2、在配置參數dfs.name.dir指定的位置建立一個空文件夾;把檢查點目錄的位置賦值給配置參數fs.checkpoint.dir;啟動NameNode,並加上-importCheckpoint。(這句話抄襲的是hadoop-0.20.2/hadoop-0.20.2/docs /cn/hdfs_user_guide.html#Secondary+NameNode,看看文檔,有說明)
3、啟動namenode的時候采用hadoop namenode –importCheckpoint
五、總結
1、secondarynamenode可以配置多個,master文件里面多寫幾個就可以。
2、千萬記得如果要恢復數據是需要手動拷貝到namenode機器上的。不是自動的(參看上面寫的恢復操作)。
3、鏡像備份的周期時間是可以修改的,如果不想一個小時備份一次,可以改的時間短點。core-site.xml中的fs.checkpoint.period值