而SecondaryNameNode,会周期性的将EditLog中记录的对HDFS的操作合并到一个checkpoint中,然后清空 EditLog。所以namenode的重启就会Load最新的一个checkpoint,并replay EditLog中 记录的hdfs操作,由于EditLog中记录的是从 上一次checkpoint以后到现在的操作列表,所以就会比较小。如果没有snn的这个周期性的合并过程,那么当每次重启namenode的时候,就会 花费很长的时间。而这样周期性的合并就能减少重启的时间。同时也能保证HDFS系统的完整性。
属性blocksMap:
//
// Mapping: 数据块 -> { inode节点, datanode列表, self ref } // Updated only in response to client-sent information.
//
final BlocksMap blocksMap = new BlocksMap(DEFAULT_INITIAL_MAP_CAPACITY,
DEFAULT_MAP_LOAD_FACTOR);
属性datanodeMap:
NavigableMap datanodeMap =
new TreeMap();
这个treemap存储了每个DataNode对应的元信息;
属性heartbeats用于heartbeat线程监控使用:
ArrayList heartbeats = new ArrayList();记录的是存活的datanode节点信息
private Map> recentInvalidateSets =new TreeMap>();//无用block列表
假如现在要获取某个datanode上的n个节点的话,先要去datanodeMap中获取DatanodeDescriptor信息,然后获取BlockInfo信息
接着blocksMap中获取block存储的datanode节点id,当然假如这个block在recentInvalidateSets列表中那就要过滤掉。
属性dir
//
// Stores the correct file name hierarchy
//这个文件中存储了每个文件名对应的位置也就是命名空间
//
public FSDirectory dir;
接下来我们要关注一下FSNamesystem的初始化过程:
while (!allAlive) {
boolean foundDead = false;
DatanodeID nodeID = null;
// 在datanode节点列表中查找第一个dead了的
synchronized(heartbeats) {
for (Iterator it = heartbeats.iterator();
it.hasNext();) {
DatanodeDescriptor nodeInfo = it.next();
if (isDatanodeDead(nodeInfo)) {//datanode的meta信息中上次更新时间超过一定阀值
foundDead = true;
nodeID = nodeInfo;
break;
}
}
}
//移出已经死了的节点
if (foundDead) {
synchronized (this) {
synchronized(heartbeats) {
synchronized (datanodeMap) {
DatanodeDescriptor nodeInfo = null;
try {
nodeInfo = getDatanode(nodeID);
} catch (IOException e) {
nodeInfo = null;
}
if (nodeInfo != null && isDatanodeDead(nodeInfo)) {
NameNode.stateChangeLog.info("BLOCK* NameSystem.heartbeatCheck: "
+ "lost heartbeat from " + nodeInfo.getName());
removeDatanode(nodeInfo);
}
}
}
}
}
allAlive = !foundDead;
}
移出操作过程是这样的:
//从heartbeats中移出
synchronized (heartbeats) {
if (nodeInfo.isAlive) {
updateStats(nodeInfo, false);
heartbeats.remove(nodeInfo);
nodeInfo.isAlive = false;
}
}
//删除该node对应的block信息
for (Iterator it = nodeInfo.getBlockIterator(); it.hasNext();) {
removeStoredBlock(it.next(), nodeInfo);
}
unprotectedRemoveDatanode(nodeInfo);
//将其从拓扑结构中移出
clusterMap.remove(nodeInfo);
ReplicationMonitor线程负责数据块的多个备份和监控工作