hadoop namenode后需要带上一系列参数才能顺利执行。执行hadoop namenode时,会从org.apache.hadoop.hdfs.server.namenode.NameNode进入hadoop,通过参数的不同调用不同的方法对namenode进行操作。
try {
StringUtils.startupShutdownMessage(NameNode.class, argv, LOG);
NameNode namenode = createNameNode(argv, null);
if (namenode \!= null)
namenode.join();
} catch (Throwable e) {
LOG.error(StringUtils.stringifyException(e));
System.exit(-1);
}
hadoop namenode -format
格式化namenode。在安装好一个新的空白的hadoop后,需要对hdfs进行格式化,生成干净的元数据。format以后,才能进行后续的动作将空白的hadoop集群启动。主要生成以下几个文件:
文件名 | 作用 |
---|---|
dfs.name.dir/current/fsimage | hdfs中文件的元数据信息,启动时候会和edits文件合并后加载到内存,构成完整的元数据信息 |
dfs.name.dir/current/VERSION | 当前hadoop集群的版本信息,NamespaceId等 |
dfs.name.dir/image/fsimage | 阻止早期版本使用这个fsimage启动(0.13以前) |
dfs.name.edits.dir/current/edits | 保存对元数据进行的每次操作,比如创建文件,删除 文件。类似于mysql中的binlog机制。 |
NameNode.createNameNode是会判断是否是format,具体的源码执行过程如下:
case FORMAT:
boolean aborted = format(conf, true);
System.exit(aborted ? 1 : 0);
进入format方法后,会读取到配置项中配置的dfs.name.dir目录和dfs.name.edits.dir目录。
dfs.name.dir用于保存hadoop集群的元数据信息
dfs.name.edits.dir用于保存NameNode的editlog,记录对hdfs的每一步操作。
Collection<File> dirsToFormat = FSNamesystem.getNamespaceDirs(conf);
Collection<File> editDirsToFormat = FSNamesystem.getNamespaceEditsDirs(conf);
之后执行格式化的操作
FSNamesystem nsys = new FSNamesystem(new FSImage(dirsToFormat,editDirsToFormat), conf);
nsys.dir.fsImage.format();
format()操作会调用FsImage.format(StorageDirectory sd)方法,循环处理每个目录。在format中:
sd.clearDirectory(); // 删除目录中的current目录,并重新创建current目录
sd.lock();
try {
saveCurrent(sd);//往current目录中写入内容
} finally {
sd.unlock();
}
根据目录类型来调用不同的写入文件方法,IMAGE目录:
FSImage.saveFSImage(getImageFile(sd, NameNodeFile.IMAGE));
往current/fsimage中写入如下信息:
out.writeInt(FSConstants.LAYOUT_VERSION); //版本信息
out.writeInt(namespaceID);//namespaceid,每次调用format()方法是生成的随机数
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);//保存根节点的相关信息,如replication数量,修改时间,访问时间,块数,权限状态等等。
// save the rest of the nodes
saveImage(strbuf, 0, fsDir.rootDir, out);//保存子节点的相关信息,这是个递归过程,会把节点的整个子树都遍历一遍
fsNamesys.saveFilesUnderConstruction(out);//写入现在与租约关联的block的相关信息
fsNamesys.saveSecretManagerState(out);
写完后fsimage的数据格式如下图:
EDITS目录:
FSEditLog.createEditLogFile(getImageFile(sd, NameNodeFile.EDITS));//创建current/edits文件
最后调用Storage.write()写入版本信息相关内容
corruptPreUpgradeStorage(root);//创建$DATA/name/image/fsimage作为废弃文件让hadoop 0.13之前的版本不能够使用这个目录来启动
write(getVersionFile()); //编写current/VERSION文件
这些数据文件都创建完成后,一个空白的hadoop就能够在下一步正常启动了
整个format的大致流程如下: