加入收藏 | 设为首页 | 会员中心 | 我要投稿 | RSS
您当前的位置:首页 > 教程文章 > NOSQL数据库

Hadoop源代码分析(30)

时间:2012-04-27 00:26:25  来源:  作者:

软柿子都捏完了,我们开始啃硬骨头。前面已经分析过getBlockLocations,create,append,setReplication,setPermission和setOwner,接下来我们继续回来讨论和文件内容相关的操作。

public void abandonBlock(Block b, String src, String holder
) throws IOException;
abandonBlock用于放弃一个数据块。普通的文件系统中并没有“放弃”操作,HDFS出现放弃数据块的原因,如下图所示。当客户端通过其他操作(如下面要介绍的addBlock方法)获取LocatedBlock后,可以打开到一个block的输出流,由于从DataNode出错到NameNode发现这个信息,需要有一段时间(NameNode长时间收到DataNode心跳),打开输出流可能出错,这时客户端可以向NameNode请求放弃这个数据块。
abandonBlock的处理不是很复杂,首先检查租约(调用checkLease方法。block对应的文件存在,文件处于构造状态,租约拥有者匹配),如果通过检查,调用FSDirectory的removeBlock,从INodeFileUnderConstruction/BlocksMap/CorruptReplicasMap中删除block,然后通过logOpenFile()记录变化(logOpenFile真是万能啊)。
public LocatedBlock addBlock(String src, String clientName) throws IOException;
HDFS的文件时,如果数据块被写满,客户端可以通过addBlock创建新的数据块。具体的创建工作由FSNamesystem的getAdditionalBlock方法完成,当然上来就是一通检查(是否安全模式,命名/存储空间限额,租约,数据块副本数,保证DataNode已经上报数据块状态),然后通过ReplicationTargetChooser,选择复制的目标(如果目标数不够副本数,又是一个异常),然后,就可以分配数据块了。allocateBlock创建一个新的Block对象,然后调用addBlock,检查参数后把数据块加到BlocksMap对象和对应的INodeFile对象中。allocateBlock返回后,getAdditionalBlock还会继续更新一些需要记录的信息,最后返回一个新构造的LocatedBlock。
public boolean complete(String src, String clientName) throws IOException;
当客户端完成对数据块的写操作后,调用complete完成写操作。方法complete如果返回是false,那么,客户端需要继续调用complete方法。
FSNamesystem的同名方法调用completeFileInternal,它会:
l检查环境;
l获取src对应的INode;
l如果INode存在,并且处于构造状态,获取数据块;
l如果获取数据块返回空,返回结果CompleteFileStatus.OPERATION_FAILED,FSNamesystem的complete会抛异常返回;
l如果上报文件完成的DataNode数不够系统最小的副本数,返回STILL_WAITING;
l调用finalizeINodeFileUnderConstruction;
l返回成功COMPLETE_SUCCESS
其中,对finalizeINodeFileUnderConstruction的处理包括:
l释放租约;
l将对应的INodeFileUnderConstruction对象转换为INodeFile对象,并在FSDirectory进行替换;
l调用FSDirectory.closeFile关闭文件,其中会写日志logCloseFile(path, file)。
l检查副本数,如果副本数小于INodeFile中的目标数,那么添加数据块复制任务。
我们可以看到,complete一个文件还是比较复杂的,需要释放很多的资源。
public void reportBadBlocks(LocatedBlock[] blocks) throws IOException;
调用reportBadBlocks的地方比较多,客户端可能调用,DataNode上也可能调用。

 

 

由于上报的是个数组,reportBadBlocks会循环处理,调用FSNamesystem的markBlockAsCorrupt方法。markBlockAsCorrupt方法需要两个参数,blk(数据块)和dn(所在的DataNode信息)。如果系统目前副本数大于要求,那么直接调用invalidateBlock方法。

 

 

方法invalidateBlock很简单,在检查完系统环境以后,先调用addToInvalidates方法往FSNamesystem.recentInvalidateSets添加一项,然后调用removeStoredBlock方法。

removeStoredBlock被多个方法调用,它会执行:
lBlocksMap中删除记录removeNode(block, node);
l如果目前系统中还有其他副本,调用decrementSafeBlockCount(可能的调整安全模式参数)和updateNeededReplications(跟新可能存在的block复制信息,例如,现在系统中需要复制1个数据块,那么更新后,需要复制2个数据块);
l如果目前系统中有多余数据块等待删除(在excessReplicateMap中),那么移除对应记录;
l删除在CorruptReplicasMap中的记录(可能有)。
removeStoredBlock其实也是涉及了多处表操作,包括BlocksMap,excessReplicateMap和CorruptReplicasMap。
我们回到markBlockAsCorrupt,如果系统目前副本数小于要求,那么很显然,我们需要对数据块进行复制。首先将现在的数据块加入到CorruptReplicasMap中,然后调用updateNeededReplications,跟新复制信息。
markBlockAsCorrupt这个流程太复杂了,我们还是画个图吧:


 
来顶一下
返回首页
返回首页
发表评论 共有条评论
用户名: 密码:
验证码: 匿名发表
推荐资讯
在CentOS下搭建Android 开发环境
在CentOS下搭建Androi
轻松搭建属于自己的Ubuntu发行版
轻松搭建属于自己的Ub
利用SUSE Studio 打造自己的个性化Linux发行版
利用SUSE Studio 打造
那些采用PHP技术的IT大企业
那些采用PHP技术的IT大
相关文章
    无相关信息
栏目更新
栏目热门