fsimage 的当前版本号位165,从最后一个检查点fsimage165正在进行的edits_inprogress日志编号为166,
在下次namenode重启时,它将与fsimage165合并,fsimage166将被创建。
Secondary NameNode 当前目录的截图如下:
注意,在namenode中没有对应的实时编辑edits_inprogress_166版本。
此时有fsimage165,那么在进行合并的时候不需要从NameNode把fsimage也传输过来吧?
但是执行合并的时候输出的日志:
这看起来好像是需要下载fsimage
瞬间蒙圈了。
没办法只能去老老实实去瞄一下源码了:
下面只展示核心代码:
//org.apache.Hadoop.hdfs.server.namenode.SecondaryNameNode#doCheckpoint
/**
* 创建一个新的检查点
* @return image 是否从NameNode获取
*/
@VisibleForTesting
@SuppressWarnings("deprecated")
public boolean doCheckpoint() throws IOException {
//告诉namenode在一个新的编辑文件中开始记录事务,将返回一个用于上传合并后的image的token。
CheckpointSignature sig = namenode.rollEditLog();
//是否重新加载fsimage
boolean loadImage = false;
//这里需要reload fsImage有两种情况
//1. downloadCheckpointFiles中判断fsiamge变化情况
//2. 是否发生checkpointImage 和并错误
loadImage |= downloadCheckpointFiles(
fsName, checkpointImage, sig, manifest) |
checkpointImage.hasMergeError();
//执行合并操作
doMerge(sig, manifest, loadImage, checkpointImage, namesystem);
}
// org.apache.Hadoop.hdfs.server.namenode.SecondaryNameNode#downloadCheckpointFiles
/**
* 从name-node 下载 fsimage 和 edits
* @return true if a new image has been downloaded and needs to be loaded
* @throws IOException
*/
static boolean downloadCheckpointFiles(...) throws IOException {
//根据Image的变化情况决定是否download image
if (sig.mostRecentCheckpointTxId ==
dstImage.getStorage().getMostRecentCheckpointTxId()) {
LOG.info("Image has not changed. Will not download image.");
} else {
LOG.info("Image has changed. Downloading updated image from NN.");
MD5Hash downloadedHash = TransferFsImage.downloadImageToStorage(
nnHostPort, sig.mostRecentCheckpointTxId,
dstImage.getStorage(), true, false);
dstImage.saveDigestAndRenameCheckpointImage(NameNodeFile.IMAGE,
sig.mostRecentCheckpointTxId, downloadedHash);
}
// download edits
for (RemoteEditLog log : manifest.getLogs()) {
TransferFsImage.downloadEditsToStorage(
nnHostPort, log, dstImage.getStorage());
}
// true if we haven't loaded all the transactions represented by the downloaded fsimage.
return dstImage.getLastAppliedTxId() < sig.mostRecentCheckpointTxId;
}
// org.apache.Hadoop.hdfs.server.namenode.SecondaryNameNode#doMerge
void doMerge(...) throws IOException {
//如果需要load iamge 就reload image
if (loadImage) dstImage.reloadFromImageFile(file, dstNamesystem);
Checkpointer.rollForwardByApplyingLogs(manifest, dstImage, dstNamesystem);
// 清除旧的fsimages 和edits
dstImage.saveFSImageInAllDirs(dstNamesystem, dstImage.getLastAppliedTxId());
}
从上面的核心代码可以看到,进行合并的时候,是否需要从NameNode load fsiamge是要看情况的。
不过目前fsiamge 是否改变这点没有深入看源码,
猜测大概是初次启动NameNode时,合并出新的fsiamge(如上面的image_165与 edits_166 合并出来的image_166)。
与当前Secondary NameNode 中的image_165不一致了,所以需要重新拉取,
具体以后有时间再看看。
但是只要记住有些场景下会把fsimage load下来,有些场景不会就可以了。
后续的内容
“怎么样,罗拉,这个简单的介绍可以吧”?
“还行,但是就这么简单?”罗拉狐疑。
“简单?这都是经过前人的努力才搞出来的,而且这是简单的介绍,实际上我们现在再生产用的和这个其实都不太一样了。”
“有多大差别?”
“我现在这里没有给你介绍Hdfs读写流程,还有现在NameNode其实还存在问题,统一的资源管理Yarn也没说,早着呢。”
“还有,想真正掌握,还的去追下源码看看这个操作是怎么实现的。就我现在说的这些,去面试都过不了。”八哥无限鄙视
“哦,那就是说你讲的不完善,今晚的碗我不洗,等你讲完了再说。”
“这么赖皮的嘛?....”
后面有几个点会单独拿出来写个文章,主要是以下几个方面的内容:
Hdfs读写流程
Yarn统一资源管理
Hdfs HA(高可用)
Hdfs读写源码解析(会用3.1.3的源码)