正在跑Spark任务的时候,代码提交上去了,代码提交之后肯定是要通过yarn上传到HDFS上面,然后各个节点就可以看到jar包了。
但是这个时候突然间报错NameNode进入了安全模式。【注:进入安全模式之后你就只能查看hdfs上面的内容,不能创建。因此上传jar包失败】。于是我去查看集群,发现HDFS挂了,数据丢失率达到90%多,然后HBase也挂了【这个是当然的,HDFS进入安全模式之后HBase的Master进程也会挂掉】。
那么问题来了。
因为根本原因是HDFS的数据块丢失导致了一系列的问题,那么只能查找HDFS了,于是就开始了追查日志的旅程,看到报错日志为,大部分的报错日志为NameNode进入了安全模式,一直追到源头发现这个Namenode是从备份状态切换来的,而另一台NameNode显然挂的比它要早。
切换日志,继续追踪。。。
看到报错日志之前最初是这种类型【这些不是Error级别的日志是INFO级别的】
org.apache.hadoop.hdfs.server.datanode.checker.ThrottledAsyncChecker: Scheduling a check for /xxx/xxx/dfs/dn
然后是这种日志
2019-12-05 16:47:40,269 INFO org.apache.hadoop.hdfs.server.datanode.fsdataset.impl.FsDatasetAsyncDiskService: Deleted BP-402578992-132.46.XXX-XX-XXXX881445150 blk_1093729618_19992285 URI file:/xxx/xxx/dfs/dn/current/BP-402578992-132.46.XXX-XX-XXXX881445150/current/finalized/subdir16/subdir29/blk_1093729618
2019-12-05 16:47:40,272 INFO org.apache.hadoop.hdfs.server.datanode.fsdataset.impl.FsDatasetAsyncDiskService: Deleted BP-402578992-132.46.XXX-XX-XXXX881445150 blk_1093333597_19596217 URI file:/xxx/xxx/dfs/dn/current/BP-402578992-132.46.XXX-XX-XXXX881445150/current/finalized/subdir10/subdir18/blk_1093333597
后面就是NameNode进入安全模式的报错。
这说明datanode开始进行自检了,然后移除了一些块信息,那么问题来了。
请大家回忆一下hdfs启动流程:DataNode是会向NameNode汇报自己的块位置的。
因此这个问题出在DataNode,他为什么所有的块都少了呢?
因为这几天对集群进行扩容,扩容的节点和原来的节点相比硬盘少了9块,因此这些节点在配置的时候可能修改错了地方。于是去CDH管理页面进行查看,果然是这样。
原本的集群10块硬盘都配置到了hdfs上面,但是现在只剩下一块了,因此这就是问题所在。
进入管理页面改回来,但是改的时候把所有的节点都改为了10个硬盘【对应到配置上面就是10个目录】,于是新的问题又产生了,那些没有挂载硬盘的目录很快就满了。
于是集群又进入了报警状态。
于是找到这个原因之后将扩容的节点这几个目录删掉【单独删除这几台,其他节点不动】,重启集群,发现报错少了,但是确实回到了最初块丢失了,这次的丢失是因为启动到发现问题的期间来的数据已经进入这些没有挂载硬盘的目录,那么删除的数据就会把这些数据删除掉。
这次虽然也是丢失了块,但是丢失率小于0.01,因此NameNode没有进入安全模式,但是数据确实丢了,CDH显示丢失103个块。
查看那些数据丢失了
将丢失的块重定向到日志中
hdfs fsck / | egrep -v '^\.+$' | grep -v eplica > log
hdfs fsck -list-corruptfileblocks
#查看某一个文件的情况
hdfs fsck /path/to/corrupt/file -locations -blocks -files
可以在log中看到丢失的数据块
看网上说恢复数据是这样的【别信】,吐槽:天下文章一大抄,关键还抄的是错的
hdfs debug recoverLease -path /hbase/data/default/xxx/7f1eb0a88a2f8f960cbe975ec84905a5/r/c5abbd43022b4b688767a1722bb2e4be -retries 10
但是实际上我感觉都是以讹传讹,他真的把数据恢复了吗?当然是没有的,那么它做的是什么工作呢?
as you know,HDFS是基于租约的。通俗地说:客户端每次对hdfs的读写请求之前都要获取租约,结束之后释放租约。那么这个命令就是手动释放租约的。点击进入官网查询此命令,文章最后既是该命令
查询数据看看能不能找回或者重新入库,如果可以,重来一下。如果不能那么也没办法。
查看丢了什么数据之后就把它删了吧,放着也没什么用,当然如果你磁盘没有删除还可以恢复的话另说。
删除命令
#/xxx/xxx 为相应的路径eg:/hbase/data/default/test/region01/c/uuid1
hdfs fsck /xxx/xxx -delete
此次的丢失数据,丢失的块对应到HBase上面为StoreFile。因此HBase的元数据是没有错的,因此它依旧可以找到每一个region。但是如果是这个region丢失的有StoreFile,那么这个region就会丢失一部分相应的数据。也就是丢了这个StoreFile对应的数据。
当然如果你整个region都丢了而不是一个StoreFile那么另说。