Hadoop2源码分析-HDFS核心模块分析
1.概述
这篇博客接着《Hadoop2源码分析-RPC机制初识》来讲述,前面我们对MapReduce、序列化、RPC进行了分析和探索,对Hadoop V2的这些模块都有了大致的了解,通过对这些模块的研究,我们明白了MapReduce的运行流程以及内部的实现机制,Hadoop的序列化以及它的通信机制(RPC)。今天我们来研究另一个核心的模块,那就是Hadoop的分布式文件存储系统——HDFS,下面是今天分享的内容目录:
- HDFS简述
- NameNode
- DataNode
接下来,我们开始今天的分享内容。
2.HDFS简述
HDFS全称Hadoop Distributed File System,在HDFS中有几个基本的概念,首先是它的数据块(Block),HDFS的设计是用于支持大文件的。运行在HDFS上的程序也是用于处理大数据集的。这些程序仅写一次数据,一次或多次读数据请求,并且这些读操作要求满足流式传输速度。HDFS支持文件的一次写多次读操作。HDFS中典型的块大小是64MB,一个HDFS文件可以被被切分成多个64MB大小的块,如果需要,每一个块可以分布在不同的数据节点上。HDFS 中,如果一个文件小于一个数据块的大小,并不占用整个数据块存储空间。
HDFS提供了一个可操作文件系统的抽象类org.apache.hadoop.fs.FileSystem,该类被划分在Hadoop-Common部分,其源码地址为:hadoop-2.6.0-src/hadoop-common-project/hadoop-common/src/main/java/org/apache/hadoop/fs/FileSystem.java,如下是FileSystem的部分源码,如下所示:
@InterfaceAudience.Public
@InterfaceStability.Stable
public abstract class FileSystem extends Configured implements Closeable {
// 代码内容省略
// ...
}
我们可以使用着抽象类,去操作HDFS系统上的内容,实现代码如下所示:
private static void dfs() {
FileSystem fs = null;
try {
fs = FileSystem.get(conf);// get file object
FileStatus[] list = fs.listStatus(new Path("/"));// file status list
for (FileStatus file : list) {
LOGGER.info(file.getPath().getName());// print file names
}
} catch (IOException e) {
e.printStackTrace();
LOGGER.error("Get hdfs path has error,msg is " + e.getMessage());
} finally {
try {
if (fs != null) {
fs.close();
}
} catch (IOException e) {
e.printStackTrace();
LOGGER.error("Close fs object has error,msg is " + e.getMessage());
}
}
}
下面,我们来看另一个概念是元数据节点(Namenode)和数据节点(datanode),这2个是HDFS的核心模块,下面我们分别来看看这2个核心模块。
3.NameNode
NN节点用来管理文件系统的NameSpace,将所有的文件和文件夹的Meta保存在一个文件系统中,是HDFS中文件目录和文件分配的管理者,保存的重要信息如下所示:

在HDFS集群上可能包含成百上千个DataNode(简称DN)节点,这些DN节点定时和NameNode(简称NN)节点保持通信,接受NN节点的一些指令,为了减小NN的压力,NN上并不永久存储那个DN上报的数据块信息,而是通过DN上报的状态来更新NN上的映射表信息。DN和NN建立连接后,会和NN保持心跳,心跳返回的信息包含了NN对DN的一些指令信息,如删除数据,复制数据到其他的DN节点。值得注意的是NN不会主动去请求DN,这是一个严格意义上的C/S架构模型,同时,客户端在操作HDFS集群时,DN节点会互相配合,保证数据的一致性。
NN节点信息存储,部分截图信息如下所示:


4.DataNode
下面我们来分析一下DN的实现,DN的实现包含以下部分,一部分是对本地Block的管理,另一部分就是和其他的Entity进行数据交互。首先,我们先看本地的Block管理部分。我们在搭建Hadoop集群时,会指定Block的存储路径,我们可以找到配置的存储路径,在hdfs-site.xml文件下,内容路径如下所示:
<property>
<name>dfs.datanode.data.dir</name>
<value>/home/hadoop/data/dfs/data</value>
</property>
然后,我们进入到DN节点上,找到对应的存储目录,如下图所示:

这里面in_use.lock的作用是做一个排斥操作,在对应的应用上面加锁。然后current目录存放的是当前有效的Block,进入到current目录后,出现如下图所示的目录:
VERSION存放着一些文件的Meta,接着还有一系列的Block文件和Meta文件,Block文件是存储了HDFS中的数据的。存储的Block,一个Block在多个DN节点上有备份,其备份参数可以调节,在hdfs-site.xml文件中,属性设置如下所示:
<property>
<name>dfs.replication</name>
<value>3</value>
</property>
首先,我们来看DateNode的类,部分代码如下所示:
@VisibleForTesting
@InterfaceAudience.Private
public static DataNode createDataNode(String args[], Configuration conf,
SecureResources resources) throws IOException {
DataNode dn = instantiateDataNode(args, conf, resources);// init dn
if (dn != null) {
dn.runDatanodeDaemon();// register to nn and back to dn thread
}
return dn;
}
/** Instantiate a single datanode object, along with its secure resources.
* This must be run by invoking{@link DataNode#runDatanodeDaemon()}
* subsequently.
*/
public static DataNode instantiateDataNode(String args [], Configuration conf,
SecureResources resources) throws IOException {
if (conf == null)
conf = new HdfsConfiguration(); if (args != null) {
// parse generic hadoop options
GenericOptionsParser hParser = new GenericOptionsParser(conf, args);
args = hParser.getRemainingArgs();
} if (!parseArguments(args, conf)) {
printUsage(System.err);
return null;
}
Collection<StorageLocation> dataLocations = getStorageLocations(conf);
UserGroupInformation.setConfiguration(conf);
SecurityUtil.login(conf, DFS_DATANODE_KEYTAB_FILE_KEY,
DFS_DATANODE_KERBEROS_PRINCIPAL_KEY);
return makeInstance(dataLocations, conf, resources);
}
static DataNode makeInstance(Collection<StorageLocation> dataDirs,
Configuration conf, SecureResources resources) throws IOException {
LocalFileSystem localFS = FileSystem.getLocal(conf);
FsPermission permission = new FsPermission(
conf.get(DFS_DATANODE_DATA_DIR_PERMISSION_KEY,
DFS_DATANODE_DATA_DIR_PERMISSION_DEFAULT));
DataNodeDiskChecker dataNodeDiskChecker =
new DataNodeDiskChecker(permission);
List<StorageLocation> locations =
checkStorageLocations(dataDirs, localFS, dataNodeDiskChecker);
DefaultMetricsSystem.initialize("DataNode"); assert locations.size() > 0 : "number of data directories should be > 0";
return new DataNode(conf, locations, resources);// create dn obejct
}
public void runDatanodeDaemon() throws IOException {
blockPoolManager.startAll();
// start dataXceiveServer
dataXceiverServer.start();
if (localDataXceiverServer != null) {
localDataXceiverServer.start();
}
ipcServer.start();
startPlugins(conf);
}
public static void secureMain(String args[], SecureResources resources) {
int errorCode = 0;
try {
StringUtils.startupShutdownMessage(DataNode.class, args, LOG);
DataNode datanode = createDataNode(args, null, resources);
if (datanode != null) {
datanode.join();
} else {
errorCode = 1;
}
} catch (Throwable e) {
LOG.fatal("Exception in secureMain", e);
terminate(1, e);
} finally {
// We need to terminate the process here because either shutdown was called
// or some disk related conditions like volumes tolerated or volumes required
// condition was not met. Also, In secure mode, control will go to Jsvc
// and Datanode process hangs if it does not exit.
LOG.warn("Exiting Datanode");
terminate(errorCode);
}
}
- Main函数入口
下面给出DN类的Main函数入口,代码片段如下所示:
public static void main(String args[]) {
if (DFSUtil.parseHelpArgument(args, DataNode.USAGE, System.out, true)) {
System.exit(0);
}
secureMain(args, null);
}
5.总结
在研究HDFS的相关模块时,这里需要明白各个模块的功能及作用,这里为大家介绍了DN类的部分代码片段,以及给代码片段重要部分添加了代码注释,若是大家需要了解详细的相关流程及代码,可以阅读Hadoop的HDFS部分的源代码。
6.结束语
这篇博客就和大家分享到这里,如果大家在研究学习的过程当中有什么问题,可以加群进行讨论或发送邮件给我,我会尽我所能为您解答,与君共勉!
Hadoop2源码分析-HDFS核心模块分析的更多相关文章
- Mybatis源码学习第六天(核心流程分析)之Executor分析
今Executor这个类,Mybatis虽然表面是SqlSession做的增删改查,其实底层统一调用的是Executor这个接口 在这里贴一下Mybatis查询体系结构图 Executor组件分析 E ...
- 【源码解析】Sharding-Jdbc模块分析
最新的2.0版本的Sharding-Jdbc版本,由于需要支持动态配置加载,所以最新的模块信息如下: |-sharding-jdbc |-sharding-jdbc-core |-api |-cons ...
- Mybatis源码学习第六天(核心流程分析)之Executor分析(补充)
补充上一章没有讲解的三个Executor执行器; 还是贴一下之前的代码吧;我发现其实有些分析注释还是写在代码里面比较好,方便大家理解,之前是我的疏忽,不好意思 @Override public < ...
- Hadoop2源码分析-MapReduce篇
1.概述 前面我们已经对Hadoop有了一个初步认识,接下来我们开始学习Hadoop的一些核心的功能,其中包含mapreduce,fs,hdfs,ipc,io,yarn,今天为大家分享的是mapred ...
- Hadoop2源码分析-Hadoop V2初识
1.概述 在完成分析Hadoop2源码的准备工作后,我们进入到后续的源码学习阶段.本篇博客给大家分享,让大家对Hadoop V2有个初步认识,博客的目录内容如下所示: Hadoop的渊源 Hadoop ...
- Hadoop2源码分析-YARN 的服务库和事件库
1.概述 在<Hadoop2源码分析-YARN RPC 示例介绍>一文当中,给大家介绍了YARN 的 RPC 机制,以及相关代码的演示,今天我们继续去学习 YARN 的服务库和事件库,分享 ...
- Hadoop2源码分析-RPC机制初识
1.概述 上一篇博客,讲述Hadoop V2的序列化机制,这为我们学习Hadoop V2的RPC机制奠定了基础.RPC的内容涵盖的信息有点多,包含Hadoop的序列化机制,RPC,代理,NIO等.若对 ...
- Hadoop2源码分析-YARN RPC 示例介绍
1.概述 之前在<Hadoop2源码分析-RPC探索实战>一文当中介绍了Hadoop的RPC机制,今天给大家分享关于YARN的RPC的机制.下面是今天的分享目录: YARN的RPC介绍 Y ...
- Hadoop2源码分析-RPC探索实战
1.概述 在<Hadoop2源码分析-RPC机制初识>博客中,我们对RPC机制有了初步的认识和了解,下面我们对Hadoop V2的RPC机制做进一步探索,在研究Hadoop V2的RPC机 ...
随机推荐
- 【Spark2.0源码学习】-7.Driver与DriverRunner
承接上一节内容,Client向Master发起RequestSubmitDriver请求,Master将DriverInfo添加待调度列表中(waitingDrivers),下面针对于Dri ...
- Minimum Increment to Make Array Unique LT945
Given an array of integers A, a move consists of choosing any A[i], and incrementing it by 1. Return ...
- 深入理解JVM(三)垃圾收集器和内存分配策略
3.1 关于垃圾收集和内存分配 垃圾收集和内存分配主要针对的区域是Java虚拟机中的堆和方法区: 3.2 如何判断对象是否“存活”(存活判定算法) 垃圾收集器在回收对象前判断其是否“存活”的两个算法: ...
- python入门之两种方法修改文件内容
1.占硬盘修改 import os file_name="兼职.txt" new_file_name="%s.new".% file_name old_str= ...
- Ubuntu Apache 不同端口监听不同站点
在/etc/apache2/apache2.conf 中,把项目根目录设置成默认的/var/www 不要设置在某个站点的路径下(我就是配置第一个站点时改了这里才会配置第二个站点时好久弄不出来) 在 / ...
- DedeCMS文章页去img图片width和height属性
方法一:正则匹配去除 打开include/ arc.archives.class.php,查找代码: //设置全局环境变量 $this->Fields['typename'] = $this-& ...
- Jmeter安装与实例
安装步骤: 安装环境:Windows7 安装包:JDK安装包:Jmeter安装包: 环境变量配置:变量名JAVA_HOME 值:jdk的安装路径 变量名CLASSPATH值:.;%JAV ...
- day_2安装Python解释器和pycharm
首先我们复习一下昨天的内容 ···重点 1:进制转换:二进制 与 十六进制 1111 0101 1010 转换为 f5a 2:内存分布:堆区 和 栈区 计算机的原理: 控制器 运算器 存储器 inp ...
- Docker集群管理工具 - Kubernetes 部署记录 (运维小结)
一. Kubernetes 介绍 Kubernetes是一个全新的基于容器技术的分布式架构领先方案, 它是Google在2014年6月开源的一个容器集群管理系统,使用Go语言开发,Kubernete ...
- Js之设置日期时间 判断日期是否在范围内
var now = new Date(); var startDate = new Date(); startDate.setFullYear(2018, 08, 07); startDate.set ...