我是hdfs系统的新手,遇到了一个hdfs问题。
我们有一个hdfs文件系统,服务器上的namenode(此服务器名为0002)和其他两个服务器上的datanode(这两个服务器分别名为0004和0005)。原始数据来自flume应用程序,flume中的“sink”作为hdfs。flume将原始数据(txt文件)写入服务器0004和0005上的datanode。
因此,原始数据被复制两次并保存在两台服务器下。这个系统可以正常工作一段时间,直到有一天停电。重新启动服务器时,datanode服务器(0004和0005)在namenode(0002)服务器之前重新启动。在这种情况下,原始数据仍然保存在0004和0005服务器上,但是namenode(0002)上的元数据信息丢失。块信息已损坏。问题是如何修复损坏的块而不丢失原始数据?
例如,当我们检查namenode时
hadoop fsck /wimp/contract-snapshot/year=2020/month=6/day=10/snapshottime=1055/contract-snapshot.1591779548475.csv -files -blocks -locations
我们在datanode上找到了文件名,但块已损坏。相应的文件名为:
blk_1090579409_16840906
当我们转到datanode(例如0004)服务器时,我们可以通过
find ./ -name "*blk_1090579409*"
我们在hdfs系统的虚拟路径下找到了与csv文件对应的文件“/wimp/contract snapshot/year=2020/month=6/day=10/snapshottime=1055/contract snapshot.1591779548475.csv”。该文件保存在文件夹“./subdir0/subdir235/”下,我们可以打开它并找到正确的格式。相应的元数据是二进制形式(?),我们不能直接读取。
./subdir0/subdir235/blk_1090579409
问题是,既然我们已经找到了原始文件(blk1090579409),我们如何使用这些正确的原始文件并在不丢失这些文件的情况下恢复损坏的hdfs系统?
1条答案
按热度按时间g0czyy6m1#
经过一些研究,我找到了一个解决方案,这可能不是有效的,但工作。如果有人提出更好的解决方案,请告诉我。
整个想法是复制hdfs中的所有文件,将这些文件按年/日/小时/分钟排列到不同的文件夹中,然后将这些文件夹更新到hdfs中。
我有两个datanode(0004和0005)存储数据。总数据大小为10 TB以上。文件夹结构如下(与问题相同,一个在linux上显示,另一个在windows上显示):
复制因子被设置为2,这意味着(如果没有错误发生)每个datanode都将有并且只有一个原始文件的副本。因此,我们只需扫描一个datanode上的文件夹/文件(在服务器0004上,大约5 TB以上)。根据每个文件中的修改日期和时间步长,将文件复制到备份服务器/驱动程序上的新文件夹中。幸运的是,在原始文件中,时间步长信息是可用的,例如。
2020-03-02T09:25
. 我将时间四舍五入到最接近的五分钟,父文件夹是每天的,新创建的文件夹结构如下:每五分钟扫描一次数据节点文件并将其复制到新文件夹的代码是用pyspark编写的,运行所有操作大约需要2天时间(我让代码在晚上运行)。
然后我可以每天更新hdfs上的文件夹。在hdfs上,文件夹结构如下:
创建的文件夹的结构与hdfs上的相同,命名约定也相同(在复制步骤中,我重命名每个复制的文件以匹配hdfs上的约定)。
在最后一步中,我编写java代码以便对hdfs进行操作。经过一些测试,我能够在hdfs上更新每天的数据。i、 例如,它将删除文件夹下的数据
~/year=2019/month=1/day=2/
然后上传新创建文件夹下的所有文件夹/文件~/20190102/
高达~/year=2019/month=1/day=2/
在hdfs上。我每天都做这样的手术。然后损坏的块消失,正确的文件被上传到hdfs上的正确路径。根据我的研究,在hadoop上使用fsimage文件也可以在断电前发现损坏的块,但这意味着我可能在断电后损坏hdfs上的块。因此,我决定使用所描述的方法删除损坏的块,同时保留原始文件并在hdfs上更新它们。
如果有人有更好或更有效的解决方案,请分享!