在对hbase有了一点了解后最近开始学习hadoop的相关源码,首先看了下某高人的hadoop源码分析系列http://caibinbupt.iteye.com/blog/monthblog/2008-11,看了三十几篇停了,有些看不懂,虽然代码解释的比较细但类实在太多,想一下子理清思路比较难。果断使用学习hbase时的方法,把hadoop最原始的化石版本0.1.0搞来看看,本文将介绍namenode的重要逻辑实现。
namenode初始化流程:
1.初始化FSNamespace(处理hadoop中虚拟文件系统的大多逻辑)
2.初始化配置
FSNamespace初始化
1。初始化FSDirectory
2.初始化HeartbeatMonitor,管理datanode的心跳,超时则删除此节点
3.初始化LeaseMonitor,管理hadoop的契约,会定期处理超时的操作
FSDirectory初始化:
1.loadFSImage 从image load 文件名=》blockid的map
2.saveFSImage 把1的map持久化到文件
3.this.editlog = new DataOutputStream 打开editlog的输出流,准备随时写入
0.1.0版本果然是非常的简单,namenode在启动后啥也不干,只是接受RPC请求,所以后面会以重要函数为切入介绍namenode。
FSDirectory.LoadFsImage:
作用:我们知道namenode需要维护filename-》blocksequence的map,LoadFsImage就是从image文件中load 该map
DataInputStream in = new DataInputStream(new BufferedInputStream(new FileInputStream(curFile)));
try {
int numFiles = in.readInt();
for (int i = 0; i < numFiles; i++) {
UTF8 name = new UTF8();
name.readFields(in);
int numBlocks = in.readInt();
if (numBlocks == 0) {
unprotectedAddFile(name, null);
} else {
Block blocks[] = new Block[numBlocks];
for (int j = 0; j < numBlocks; j++) {
blocks[j] = new Block();
blocks[j].readFields(in);
}
unprotectedAddFile(name, blocks);
}
}
解读:
1.很有意思,image的读写中全是直接的readField和writeField来做持久化,没有任何读写object
2.numBlocks为零即为目录
3.Block对象包括blockId,length
synchronized (rootDir) {
if (blocks != null) {
// Add file->block mapping
for (int i = 0; i < blocks.length; i++) {
activeBlocks.add(blocks[i]);
}
}
return (rootDir.addNode(name.toString(), blocks) != null);
}
执行rootDir.addNode添加该node,包括文件名和对应的blocks。
解释下INode类:
类似Linux中INode的概念,看下INode的成员变量
class INode :
public String name;
public INode parent;
public TreeMap children = new TreeMap();
public Block blocks[];
包含了文件名,父亲节点,孩子节点,和文件实际的blocks
再来看addNode方法:
INode addNode(String target, Block blks[]) {
if (getNode(target) != null) {
return null;
} else {
String parentName = DFSFile.getDFSParent(target);
if (parentName == null) {
return null;
}
INode parentNode = getNode(parentName);
if (parentNode == null) {
return null;
} else {
String targetName = new File(target).getName();
INode newItem = new INode(targetName, parentNode, blks);
parentNode.children.put(targetName, newItem);
return newItem;
}
}
}
1.首先尝试getNode,如果取到INode对象表示已经有该节点,返回失败
2.DFSFile.getDFSParent拿到parent文件夹的名字,方法是简单的字符串操作
3.拿到parent INode
4.创新新INode,并添加到parent中。这边调用了 new File().getName,没太明白,应该不会真的创建文件的,只是调用下getName方法。
再看下getNode方法:
Vector components = new Vector();
int start = 0;
int slashid = 0;
while (start < target.length() && (slashid = target.indexOf('/', start)) >= 0) {
components.add(target.substring(start, slashid));
start = slashid + 1;
}
if (start < target.length()) {
components.add(target.substring(start));
}
return getNode(components, 0);
根据'/'符把文件路径分割成一个个component,然后调用getNode(components,0)递归获取INode。
INode getNode(Vector components, int index) {
if (! name.equals((String) components.elementAt(index))) {
return null;
}
if (index == components.size()-1) {
return this;
}
// Check with children
INode child = (INode) children.get(components.elementAt(index+1));
if (child == null) {
return null;
} else {
return child.getNode(components, index+1);
}
}
这样,通过调用LoadFsImage方法就成功将Image中的数据转换为Inode对象挂到rootNode上了。
Namenode.open:
方法申明:public LocatedBlock[] open(String src)
作用:client从namenode打开一个文件
LocatedBlock包括了该文件需要的blocks和每个block对应的datanode的集合,在实际读取过程中每个block会随即从拥有该block的datanode中读出block。
public LocatedBlock[] open(String src) throws IOException {
Object openResults[] = namesystem.open(new UTF8(src));
if (openResults == null) {
throw new IOException("Cannot open filename " + src);
} else {
Block blocks[] = (Block[]) openResults[0];
DatanodeInfo sets[][] = (DatanodeInfo[][]) openResults[1];
LocatedBlock results[] = new LocatedBlock[blocks.length];
for (int i = 0; i < blocks.length; i++) {
results[i] = new LocatedBlock(blocks[i], sets[i]);
}
return results;
}
}
namesystem.open
public Object[] open(UTF8 src) {
Object results[] = null;
Block blocks[] = dir.getFile(src);
if (blocks != null) {
results = new Object[2];
DatanodeInfo machineSets[][] = new DatanodeInfo[blocks.length][];
for (int i = 0; i < blocks.length; i++) {
TreeSet containingNodes = (TreeSet) blocksMap.get(blocks[i]);
if (containingNodes == null) {
machineSets[i] = new DatanodeInfo[0];
} else {
machineSets[i] = new DatanodeInfo[containingNodes.size()];
int j = 0;
for (Iterator it = containingNodes.iterator(); it.hasNext(); j++) {
machineSets[i][j] = (DatanodeInfo) it.next();
}
}
}
results[0] = blocks;
results[1] = machineSets;
}
return results;
}
首先通过dir.getFile拿到该文件对应的blocks列表,然后从block->datanode的map中取出相应的machineSets。
namenode的主要逻辑我个人感觉搞清楚file->blockseqid和blockid->machineSet这2个map就差不多了。后面有空会分析下最新的hadoop2.0的代码。
是时候看点真正的代码了!。。。
分享到:
相关推荐
hadoop-0.1.0:最小版本的hadoop。Hadoop实现了一个分布式文件系统(Hadoop Distributed File System),简称HDFS。HDFS有高容错性的特点,并且设计用来部署在低廉的(low-cost)硬件上;而且它提供高吞吐量(high ...
基于Hadoop网站流量日志数据分析系统 1、典型的离线流数据分析系统 2、技术分析 - Hadoop - nginx - flume - hive - mysql - springboot + mybatisplus+vcharts nginx + lua 日志文件埋点的 基于Hadoop网站流量...
在网上搜集的以及本人自己总结的hadoop集群常见问题及解决办法,融合了网上常常搜到的一些文档以及个人自己的经验。
是大数据课程大作业,基于Hadoop的电影影评数据分析,需要安装Hadoop,了解MapReduce 和HDFS。
Hadoop之HDFS源代码分析 pdf版 ,从源码学习文件系统的精髓,值得一看
深入云计算:Hadoop源代码分析(修订版)
Hadoop源代码分析完整版.pdf Hadoop源代码分析 hadoop mapreduce
Hadoop分析气象数据完整版源代码(含Hadoop的MapReduce代码和SSM框架) 《分布式》布置了一道小作业,这是作业的所有代码,里面包含了Hadoop的MapReduce代码、和SSM框架显示数据的代码
Hadoop的源代码分析
先对Hadoop进行系统的阐述,然后重点介绍HDFS,分析HDFS源码
Hadoop豆瓣电影数据分析(Hadoop)操作源码
基于Hadoop部署实践对网站日志分析 1. 项目概述 本次要实践的数据日志来源于国内某技术学习论坛,该论坛由某培训机构主办,汇聚了众多技术学习者,每天都有人发帖、回帖。至此,我们通过Python网络爬虫手段进行数据...
hadoop权威指南源代码,实例代码学习。
资源名称:大数据处理系统:Hadoop源代码情景分析内容简介:Hadoop是目前重要的一种开源的大数据处理平台,读懂Hadoop的源代码,深入理解其各种机理,对于掌握大数据处理的技术有着显而易见的重要性。 本书从大数据...
HADOOP实战+源代码!很值得学习和收藏哦。
基于Hadoop大数据平台对某网站的外卖订单数据进行分析,分析结果进行可视化展示
Hadoop源代码分析(完整版).pdf
Hadoop源代码分析 分析了hadoop的一些包,一些类 ,需要对hadoop深入了解的可以看看
Hadoop源代码分析完整版.pdf