当我们发现hdfs有异常的数据块的时候,往往会使用 hdfs fsck命令来查看情况,然后使用以下两个命令
hdfs debug recoverLease -path 文件绝对路径 -retries 2
hdfs fsck -delete 文件绝对路径
但是什么情况下,用哪个,会有什么影响,其实一直没怎么认真考虑过这些问题,今天就来模拟下丢数据的场景,然后测试下这两个命令
背景
HDFS场景下,有时候某些异常会导致丢失文件块!这时候,我们如何处理这些文件块,或者说这些文件块是否还有救?
丢文件块是一种统一的说法,实际上是两种情况,一个是 Corrupt blocks,一个是Missing replicas
先说个背景知识:当我上传一个文件到HDFS,这个文件在HDFS上看得到,也可以正常使用,实际上在磁盘上会存两种类型的文件
举例:
1、blk_1073743119
2、blk_1073743119_2295.meta
第一个文件就是实际上的数据,如果你的文件是文本类型的,你甚至可以直接cat这个blk文件,另一个是这个块的meta信息,相当于有了这个meta信息,我才能知道实际的数据在哪个blk里
如果是Corrupt blocks,那基本上是namenode里有这个文件块的meta信息,但是实际磁盘上找不到真实的数据块,而且是任何一个地方都找不到了,这种情况很可能数据就丢了;另一种是Missing replicas,这是数据块的副本缺失(比如正常情况下这个文件块副本数是3个,但是丢了一个只剩下2个了,那么显示的就是miss replicas)
正文
1、模拟丢失实际数据块
(1)、hdfs创建目录,生成一个文件,上传文件到hdfs
(2)、通过fsck命令,查看到这个文件块对应的blk名称(本次测试默认是2副本,不是3副本)
hadoop fsck /block/test.md -files -blocks
(上面的命令也可以加下 -locations就能看到实际存储在哪些datanode上)
到worker的机器上执行(所以文件块在worker2和worker3上):
sudo find / -name "blk_1073742058_1234*"
/mnt/disk3/hdfs/current/BP-551425355-192.168.2.237-1616556672088/current/finalized/subdir0/subdir0/blk_1073742058_1234.meta
cat blk_1073742058
asdascnoiansc0iqnv0qinmscpasmciapmcpaosncai0ncpa
备注:当我们写入一个文件到hdfs,会生成两种类型的文件 blk_xxxx(真正的文件),blk_1073743107_后缀.meta(这个是meta信息)
(3)、将实际的文件块改名(在worker2上改的)
sudo mv blk_1073742058 back_blk_1073742058_xxxx
然后在这台机器上cat这个文件块,我们发现会先在当前机器上找这个文件,报错后,去其他机器上找
hdfs dfs -cat /block/test.md
在抛这个错之后,我发现worker1的datanode从worker3那边拉了一个备份过来了(看了worker1的datanode日志)
也就是说hdfs正常情况下,如果发现块有异常,会自动做副本的同步!
备注:fsck检测文件的时候,是检测meta信息是否存在,实际上blk文件是否存在是不会检测的,也就是说我把blk重命名了,fsck是看不出来异常的
(4)、如果将以前改掉名字的文件块名字还原回去又重启datanode
可以看到datanode会把多余的副本删除的,始终保持了2副本
(5)、同时将两个blk文件改名
然后hdfs dfs -cat /block/test.md,然后这个块就真的miss了
(6)、尝试通过hdfs debug recoverLease -path /block/test.md -retries 2修复
虽然显示成功,但是文件块还是读不了
(7)、只能将文件块元数据信息删除
hdfs fsck -delete /block/test.md
上面这个黄色的框,重启namenode就会消失
但是delete命令执行之后,这个文件块就彻底看不到了(虽然磁盘上这个数据还在,但是namenode里没有对应的信息了)
2、模拟丢失meta数据块
(1)、重新上传一个文件aaa.md
(2)、在worker2上面把meta信息的文件改掉
然后重启worker2的datanode之后,看到丢失了副本
(3)、使用debug命令修复
hdfs debug recoverlease -path /block/aaa.md
(4)、查看相应日志
看worker2的日志里,先是有找不到对应块的meta信息(因为被我rename了)
然后我修复块的时候,他开始从其他机器拉这个块过来,凑巧发现了这个块已经存在,然后把原来的实际数据块删除了,然后在另一块盘上生成了这个文件快
3、小tips
在hadoop的mapred-site.xml的配置文件里有这个参数mapreduce.client.submit.file.replication,默认为10
这个参数是我们提交一个任务到yarn上面,会默认把一些jar包文件设置成10副本,让不同的datanode机器拉取这些jar包运行的时候,可以更快,一般设置为集群datanode机器个数的开方(比如25台datanode,这个参数就改成5)
然后如果你的datanode的个数小于10,那你跑任务就会有丢失副本(Missing replicas),可以批量的修改文件的副本数来解决类似的问题
## 修复Under-replicated blocks: ## 查询到Under-replicated blocks的路径 hdfs fsck / | grep 'Under replicated' | awk -F':' '{print $1}' >> /tmp/under_replicated_files ##再根据路径进行修复 for hdfsfile in `cat /tmp/under_replicated_files`; do echo "Fixing $hdfsfile :" ; hadoop fs -setrep 副本数 $hdfsfile; done
总结
1、一般情况下,丢数据,很可能是什么磁盘异常,磁盘满了,datanode挂掉等场景,所以如果发现丢数据,可以先看下hdfs各个datanode的情况
2、理论上来说,如果所有文件块(包括副本)都丢了,那基本是没救了,只能通过 -delete 命令来清除这些块的元数据信息,避免计算引擎读这些块的时候出现异常而终止
3、hdfs debug recoverlease 这个命令回显的success,有些场景下,数据块还是异常的
4、如果一次性提交较多的任务,默认情况下就会有很多副本数为10的文件块,会导致datanode的压力,可以加大datanode的内存,或者减少提交任务的副本数
5、可以直接通过 hadoop fs -setrep 设置副本数,来释放磁盘上的空间
fsck命令详细用法,请参考:
hdfs fsck命令查看HDFS文件对应的文件块信息(Block)和位置信息:http://lxw1234.com/archives/2015/08/452.htm
菜鸡一只,如果有哪里写的不对的地方,还请大家批评指正!
好久没写文章了,年后其实还是比较忙的
累是累点,但还是有很多值得开心的事情的,努力努力~
这篇文章,基本上还是从结果来判断过程,希望以后我也有机会好好读读hdfs的源码!!