上篇说到了namenode启动过程中主要是加载fsimge,edits和接收datanode的block信息。这篇主要分析namenode加载fsimage和edits的整个过程。
首先,了解一下fsimage和edits是存放什么信息的。
在hdfs-default.xml中通过dfs.name.dir和dfs.name.edits.dir配置fsimage和edits的存放路径,默认的话是存放在一个路径下的。
FSImage类继承了Storage类,来看看Storage类的描述:
* Local storage information is stored in a separate file VERSION.
* It contains type of the node,
* the storage layout version, the namespace id, and
* the fs state creation time.
可以看到,存储信息是放在一个单独的VERSION文件中,包含了节点类型,layoutversion,namespaceId和fs创建时间,那么看看集群实际上是不是这样的:
#Mon Nov 11 15:54:28 CST 2013
namespaceID=620542034
cTime=0
storageType=NAME_NODE
layoutVersion=-32
除了VERSION外,Storage还会产生一个in_use.lock的文件,表示当前集群我已经在使用了,你们要想在启动使用是不可以的。
同样DataStorage(datanode上存放block的,配置文件项为dfs.data.dir) 也继承Storage,在datanode的dfs.data.dir目录下你也能看到这2个文件。
继续Fsimage,在下面有5个文件:
enum NameNodeFile {
IMAGE ("fsimage"),
TIME ("fstime"),
EDITS ("edits"),
IMAGE_NEW ("fsimage.ckpt"),
EDITS_NEW ("edits.new");
private String fileName = null;
private NameNodeFile(String name) {this.fileName = name;}
String getName() {return fileName;}
}
看看fsimage中的保存代码:
void saveFSImage(File newFile) throws IOException {
FSNamesystem fsNamesys = FSNamesystem.getFSNamesystem();
FSDirectory fsDir = fsNamesys.dir;
long startTime = FSNamesystem.now();
//
// Write out data
// 输出流写到fsimage文件中
DataOutputStream out = new DataOutputStream(
new BufferedOutputStream(
new FileOutputStream(newFile)));
try {
out.writeInt(FSConstants.LAYOUT_VERSION);
out.writeInt(namespaceID);
out.writeLong(fsDir.rootDir.numItemsInTree());
out.writeLong(fsNamesys.getGenerationStamp());
byte[] byteStore = new byte[4*FSConstants.MAX_PATH_LENGTH];
ByteBuffer strbuf = ByteBuffer.wrap(byteStore);
// save the root
saveINode2Image(strbuf, fsDir.rootDir, out);
// save the rest of the nodes
saveImage(strbuf, 0, fsDir.rootDir, out);
fsNamesys.saveFilesUnderConstruction(out);
fsNamesys.saveSecretManagerState(out);
strbuf = null;
} finally {
out.close();
}
LOG.info("Image file of size " + newFile.length() + " saved in "
+ (FSNamesystem.now() - startTime)/1000 + " seconds.");
}
这里面除了一些基本信息外,最主要的就是inode的信息,就是存放文件和目录的基本信息,如时间,名称,使用者等。
关于inode更具体的信息,可以参看 http://blog.csdn.net/internetman/article/details/3850186
关于fsimage中的更详细格式,请参看 http://twtbgn.iteye.com/blog/1975256
在加载fsimage的过程中,会将fsimage和edits文件读入内存中进行合并,然后再写入到fsimage中去。在集群启动后,这件事就交给了secondarynamenode去做了。