在Hadoop的HDFS(Hadoop Distributed File System)中,元数据(metadata)是文件系统的核心组成部分,它包含了文件系统的目录结构、文件与块的映射关系、块的副本位置信息等。为了确保这些元数据在故障发生时不会丢失,HDFS采用了持久化存储的策略,即将元数据保存在磁盘上,并且使用日志(edit logs)和镜像文件(fsImage)来保证元数据的一致性和可恢复性。
HDFS元数据持久化
元数据的持久化方式
fsImage文件:这是一个二进制文件,包含了文件系统的完整快照。当NameNode启动时,它会加载fsImage文件到内存中,从而快速恢复文件系统的状态。
Edit Logs:当文件系统的状态发生变化时(如创建文件、删除文件、重命名文件等),这些变化会被记录在Edit Logs中。Edit Logs是顺序写入的,这使得它们具有很高的写入性能。
Secondary NameNode:虽然名为“Secondary NameNode”,但它并不承担NameNode的备份职责。它的主要工作是合并Edit Logs和fsImage,生成一个新的fsImage,并推送给NameNode。这个过程称为Checkpoint。Secondary NameNode的存在主要是为了减轻NameNode的负担,避免单个NameNode节点成为瓶颈。
具体代码
元数据持久化相关的代码片段:
NameNode启动时加载fsImage
在NameNode的启动过程中,会加载fsImage文件到内存中。
// 在NameNode的启动代码中
FSImage fsImage = new FSImage(conf, dir, fsImageFactory);
FSEditLog editLog = new FSEditLog(conf, dir, editLogFactory);
FSNamesystem namesystem = new FSNamesystem(conf, fsImage, editLog);
namesystem.loadFSImage();
namesystem.recover();
写入Edit Logs
当文件系统状态发生变化时,会生成对应的Edit Log记录。 写入Edit Log:
// 在FSNamesystem类中
private FSEditLog editLog;
// ...
public void logSync() throws IOException {
editLog.logSync();
}
// 当文件系统的状态发生变化时,会调用以下方法
public void startLogSegment() throws IOException {
editLog.startLogSegment();
}
public void logModify(FSEditLogOp op) throws IOException {
editLog.logModify(op);
}
Secondary NameNode合并fsImage和Edit Logs
Secondary NameNode会定期合并fsImage和Edit Logs,并生成新的fsImage。 合并过程:
// 在SecondaryNameNode类中
public void doCheckpoint(long txid) throws IOException {
// ...
FSImage fsImage = new FSImage(fsImageFactory, dir, conf);
FSEditLog editLog = new FSEditLog(editLogFactory, dir, conf);
CheckpointSignature signature = new CheckpointSignature(conf);
// Merge fsImage and Edit Logs
long newTxid = fsImage.merge(editLog, signature, txid);
// ...
// Push the new fsImage to the NameNode
NameNode.pushImageToActiveNN(new FSImage(fsImageFactory, dir, conf),
dir, conf, nnAddress);
// ...
}
在HDFS的实际实现中,这个过程要复杂得多,涉及到多线程同步、错误处理、恢复机制等多个方面。