摘自:http://hmilyzhangl.iteye.com/blog/1407214
一.崩溃原因
搭建的是一个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 ,增加
- < property >
- < name > fs.checkpoint.period </ name >
- < value > 3600 </ value >
- < description > The number of seconds between two periodic checkpoints. </ description >
- </ property >
- < property >
- < name > fs.checkpoint.size </ name >
- < value > 67108864 </ value >
- < description > The size of the current edit log (in bytes) that triggers a periodic checkpoint even if the fs.checkpoint.period hasn't expired. </ description >
- </ property >
- < property >
- < name > fs.checkpoint.dir </ name >
- < value > /data/work/hdfs/namesecondary </ value >
- < 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. </ description >
- </ property >
fs.checkpoint.period表示多长时间记录一次hdfs的镜像。默认是1小时。
fs.checkpoint.size表示一次记录多大的size,默认64M
2.修改conf/hdfs-site.xml
,增加
- < property >
- < name > dfs.http.address </ name >
- < value > master:50070 </ value >
- < 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. </ description >
- </ 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
<property>
<name>dfs.balance.bandwidthPerSec</name>
<value>20971520</value>
<description>
Specifies the maximum bandwidth that each datanode can utilize for the
balancing purpose in term of the number of bytes per second.
</description>
</property>
然后结果是导致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<INode> 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<Block, BlockInfo>.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文件,加上如下选项:
- <property>
- <name>dfs.http.address</name>
- <value>namenode.hadoop-host.com:50070 </value>
- </property>
core-site.xml:这里有2个参数可配置,但一般来说我们不做修改。fs.checkpoint.period表示多长时间记录一次hdfs的镜像。默认是1小时。fs.checkpoint.size表示一次记录多大的size,默认64M。
- <property>
- <name>fs.checkpoint.period</name>
- <value>3600 </value>
- <description>The number of seconds between two periodic checkpoints.
- </description>
- </property>
- <property>
- <name>fs.checkpoint.size</name>
- <value>67108864 </value>
- <description>The size of the current edit log (in bytes) that triggers
- a periodic checkpoint even if the fs.checkpoint.period hasn't expired.
- </description>
- </property>
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值