---------------------------------------------------------------------------------------------------------------

[版权申明:本文系作者原创,转载请注明出处]

文章出处:http://blog.csdn.net/sdksdk0/article/details/51622547

作者:朱培

---------------------------------------------------------------------------------------------------------------

本文主要介绍了hdfs的基本原理、hdfs基本操作、hdfs的读取数据流程、namenode工作机制,rpc编程以及常见的两种必会的面试题等,旨在于全面深入的理解HDFS的基本工作流程并可以开发出简易的HDFS的程序。

一、HDFS简介

Hadoop分布式文件系统(HDFS)被设计成适合运行在通用硬件(commodity hardware)上的分布式文件系统。HDFS体系结构中有两类节点,一类是NameNode,又叫"元数据节点";另一类是DataNode,又叫"数据节点"。这两类节点分别承担Master和Worker具体任务的执行节点。总的设计思想:分而治之——将大文件、大批量文件,分布式存放在大量独立的服务器上,以便于采取分而治之的方式对海量数据进行运算分析。

HDFS是一个主/从(Mater/Slave)体系结构,从最终用户的角度来看,它就像传统的文件系统一样,可以通过目录路径对文件执行CRUD(Create、Read、Update和Delete)操作。但由于分布式存储的性质,HDFS集群拥有一个NameNode和一些DataNode。NameNode管理文件系统的元数据,DataNode存储实际的数据。客户端通过同NameNode和DataNodes的交互访问文件系统。客户端联系NameNode以获取文件的元数据,而真正的文件I/O操作是直接和DataNode进行交互的。

HDFS一般是用来“一次写入,多次读取”,不适合做实时交互性很强的事情,不适合存储大量小文件(当然,如果你偏要存大量小文件的话本文末尾会有解决方案).

二、HDFS工作原理

2.1基本原理

1 分布式文件系统,它所管理的文件是被切块存储在若干台datanode服务器上.



2 hdfs提供了一个统一的目录树来定位hdfs中的文件,客户端访问文件时只要指定目录树的路径即可,不用关心文件的具体物理位置.



3 每一个文件的每一个切块,在hdfs集群中都可以保存多个备份(默认3份),在hdfs-site.xml中,dfs.replication的value的数量就是备份的数量.



4 hdfs中有一个关键进程服务进程:namenode,它维护了一个hdfs的目录树及hdfs目录结构与文件真实存储位置的映射关系(元数据).而datanode服务进程专门负责接收和管理"文件块"-block.默认大小为128M(可配置),(dfs.blocksize).(老版本的hadoop的默认block是64M的)

2.2 常用操作

hdfs的根目录,通过这条命令可以查看hdfs存储的文件,在hadoop的安装目录下面:

bin/hdfs dfs -ls /<pre name="code" class="html">hdfs dfs -chmod 600 /test.txt    //设置文件权限

bin/hdfs dfs -df -h /    //查看磁盘空间

bin/hdfs dfs -mkdir /aaa   //新建文件夹

bin/hdfs dfs  -tail       //查看文件尾部

hdfs块的存储位置位于:(在hadoop的根目录下面的tmp文件夹中)hadoop-2.5.2/tmp/hadoop/dfs/data/current/BP-33587274-127.0.0.1-1465370300743/current/finalized

从图中我们可以看到hdfs存储的块的,当然这里面的两个块通过合并可以形成一个新的文件,然后可以通过解压进行验证。

touch full hadoop.tar.gz
cat blk_1073741825 >> hadoop.tar.gz
cat blk_1073741826 >> hadoop.tar.gz
tar -xvzf hadoop.tar.gz

同样,在hadoop的安装目录中,直接用命令来存取文件可以通过下面的命令:

存文件:

./hdfs dfs -put /home/admin1/桌面/test.txt  hdfs://localhost:9000/

取文件:

./hdfs dfs -get hdfs://localhost:9000/test.txt





hdfs的权限控制:

客户端的操作命令

bin/hdfs dfs -chown  aa:bgroup  /test.txt    

//将test.txt文件的权限改为aa用户的bgroup组.



(因为我根本就没有这个组和用户,但是也可以修改成功,所以说明hadoop本身对权限的控制不是很严格)

2.3 HDFS的shell操作

--appendToFile  ----追加一个文件到已经存在的文件末尾

-->hadoop fs  -appendToFile  ./hello.txt hdfs://hadoop-server01:9000/hello.txt

可以简写为:

Hadoop fs  -appendToFile  ./hello.txt /hello.txt

-cat  ---显示文件内容

-->hadoop fs -cat /hello.txt

-chgrp

-chmod

-chown

上面三个跟linux中的用法一样

-->hadoop fs -chmod 666 /hello.txt

-copyFromLocal    #从本地文件系统中拷贝文件到hdfs路径去

-->hadoop fs  -copyFromLocal  ./jdk.tar.gz /aaa/

-copyToLocal      #从hdfs拷贝到本地

Eg: hadoop fs -copyToLocal /aaa/jdk.tar.gz

-count         #统计一个指定目录下的文件节点数量

-->hadoop fs -count /aaa/

-cp              #从hdfs的一个路径拷贝hdfs的另一个路径

hadoop fs -cp/aaa/jdk.tar.gz /bbb/jdk.tar.gz.2

-createSnapshot

-deleteSnapshot

-renameSnapshot

以上三个用来操作hdfs文件系统目录信息快照

-->hadoop fs -createSnapshot /

-df               #统计文件系统的可用空间信息

-du

-->hadoop fs -df -h /

-->hadoop fs -du -s -h /aaa/*

-get              #等同于copyToLocal,就是从hdfs下载文件到本地

-getmerge             #合并下载多个文件

--> 比如hdfs的目录 /aaa/下有多个文件:log.1, log.2,log.3,...

hadoop fs -getmerge /aaa/log.* ./log.sum

-help             #输出这个命令参数手册

-ls                  #显示目录信息

-->hadoop fs -ls hdfs://hadoop-server01:9000/

这些参数中,所有的hdfs路径都可以简写

-->hadoop fs -ls /   等同于上一条命令的效果

-mkdir              #在hdfs上创建目录

-->hadoop fs -mkdir -p /aaa/bbb/cc/dd

-moveFromLocal            #从本地剪切粘贴到hdfs

-moveToLocal              #从hdfs剪切粘贴到本地

-mv                     #在hdfs目录中移动文件

-put                #等同于copyFromLocal

-rm                #删除文件或文件夹

--> hadoop fs -rm -r/aaa/bbb/

-rmdir                 #删除空目录

-setrep                #设置hdfs中文件的副本数量

-->hadoop fs -setrep 3 /aaa/jdk.tar.gz

-stat                  #显示一个文件或文件夹的元信息

-tail                  #显示一个文件的末尾

-text                  #以字符形式打印一个文件的内容

三、HDFS写入数据流程解析

3.1 基本原理

hdfs的数据写入是非常复杂的过程,下面来看一下简要的步骤。

那么问题来了,如果他们之间的一个datanode突然坏掉了怎么办。

1、如果传输过程中,有某个datanode出现了故障,那么当前的pipeline会被关闭,出现故障的datanode会从当前的pipeline中移除,剩余的block会继续剩下的datanode中继续以pipeline的形式传输,同时Namenode会分配一个新的datanode,保持replicas设定的数量。

2、关闭pipeline,将ack queue中的数据块放入data queue的开始。

3、当前的数据块在已经写入的数据节点中被元数据节点赋予新的标示,则错误节点重启后能够察觉其数据块是过时的,会被删除。

4、失败的数据节点从pipeline中移除,另外的数据块则写入pipeline中的另外两个数据节点。

5、元数据节点则被通知此数据块是复制块数不足,将来会再创建第三份备份。

6、客户端调用create()来创建文件

7、DistributedFileSystem用RPC调用元数据节点,在文件系统的命名空间中创建一个新的文件。

8、元数据节点首先确定文件原来不存在,并且客户端有创建文件的权限,然后创建新文件。

9、DistributedFileSystem返回DFSOutputStream,客户端用于写数据。

10、客户端开始写入数据,DFSOutputStream将数据分成块,写入data queue。

11、Data queue由Data Streamer读取,并通知元数据节点分配数据节点,用来存储数据块(每块默认复制3块)。分配的数据节点放在一个pipeline里。

12、Data Streamer将数据块写入pipeline中的第一个数据节点。第一个数据节点将数据块发送给第二个数据节点。第二个数据节点将数据发送给第三个数据节点。

13、DFSOutputStream为发出去的数据块保存了ack queue,等待pipeline中的数据节点告知数据已经写入成功。

3.2 编码实践

这段代码的意思是从/home/admin1/hadoop/eclipse.tar.gz上传文件到hdfs文件中,URI中写的是hdfs的地址
@Test
public void testUpload() throws IOException, InterruptedException, URISyntaxException{
Configuration conf = new Configuration(); //to get a client of the hdfs system
FileSystem fs = FileSystem.get(new URI("hdfs://ubuntu2:9000"),conf,"admin1"); fs.copyFromLocalFile(new Path("/home/admin1/hadoop/eclipse.tar.gz"), new Path("/"));
fs.close(); }

四、HDFS读取数据流程解析

4.1 基本原理

读取的流程比写入的流程就简单很多了。

4.2 编码实践

下载文件:
/*public static void main(String[] args) throws IOException {
//download from hdfs Configuration conf = new Configuration();
conf.set("fs.defaultFS", "hdfs://ubuntu2:9000/"); conf.set("dfs.blocksize", "64"); //to get a client of the hdfs system
FileSystem fs = FileSystem.get(conf); fs.copyToLocalFile(new Path("hdfs://ubuntu2:9000/test.txt"), new Path("/home/admin1/Downloads/test1.txt")); fs.close();
}*/

删除文件:

@Test
public void rmove() throws IOException, InterruptedException, URISyntaxException{
Configuration conf = new Configuration(); FileSystem fs = FileSystem.get(new URI("hdfs://ubuntu2:9000"),conf,"admin1"); fs.delete(new Path("/test.txt")); fs.close();
}

五、NameNode工作机制

元数据放在内存中,同时需要备份,通过日志的记录(对元数据有修改操作时)写到磁盘中,用edits_ingropress,定期dump一次,当一旦断电时,很难恢复,

所以我们就用sercondName定期把操作日志下载和内存镜像文件,然后就定期合并操作记录,(日志+fsimage)然后生成一个新的namenode镜像文件  (fs.image.ckpt)

最后上传给namenode,然后namenode重命名为fsimage.





元数据管理机制:

1、元数据有3中存储形式:内存、edits日志、fsimage

2、最完整最新的元数据一定是内存中的这一部分

六、RPC编程

使用 RPC 编程是在客户机和服务器实体之间进行可靠通信的最强大、最高效的方法之一。它为在分布式计算环境中运行的几乎所有应用程序提供基础。任何 RPC 客户机-服务器程序的重要实体都包括 IDL 文件(接口定义文件)、客户机 stub、服务器 stub 以及由客户机和服务器程序共用的头文件。客户机和服务器 stub 使用 RPC 运行时库通信。RPC 运行时库提供一套标准的运行时例程来支持 RPC 应用程序。在一般的应用程序中,被调用的过程在相同的地址空间中运行,并把结果返回给发出调用的过程。在分布式环境中,客户机和服务器在不同的机器上运行,客户端调用在服务器端运行的过程,并把结果发送回客户机。这称为远程过程调用
(RPC),是 RPC 编程的基础。

以下实例是用来模拟用户登陆的过程。

在linux中的eclipse。新建一个java工程,新建java文件:

RPCServer.java

package hdfsTest;

public interface  RPCService {
public static final long versionID=100L; //定义通信接口的版本号 public String userLogin(String username,String password); //用户名和密码 }

RPCServerImpl.java

package hdfsTest;

public class RPCServiceImpl  implements RPCService {

	@Override
public String userLogin(String username, String password) {
return username+" logged in successfully!";
}
}

RPCControl.java

package hdfsTest;

import java.io.IOException;
import java.net.InetSocketAddress; import org.apache.hadoop.conf.Configuration;
import org.apache.hadoop.ipc.RPC; //
public class RPCController { public static void main(String[] args) throws IOException {
RPCService serverceImpl=RPC.getProxy(RPCService.class,100,new InetSocketAddress("ubuntu2",10000),new Configuration());
<span style="white-space:pre"> </span>//100是指前面设置的版本号,InetSocketAddress中的是hdfs主机名和10000是通信端口
String result=serverceImpl.userLogin("aaa", "aaa"); //设置用户用户名和密码
System.out.println(result);
}
}

ServerRunner.java

package hdfsTest;

import java.io.IOException;

import org.apache.hadoop.HadoopIllegalArgumentException;
import org.apache.hadoop.conf.Configuration;
import org.apache.hadoop.ipc.RPC;
import org.apache.hadoop.ipc.RPC.Builder;
import org.apache.hadoop.ipc.Server; public class ServerRunner { public static void main(String[] args) throws HadoopIllegalArgumentException, IOException {
Builder builder=new RPC.Builder(new Configuration()); builder.setBindAddress("ubuntu2"); //hdfs的主机名
builder.setPort(10000); //设置通信端口号 builder.setProtocol(RPCService.class);
builder.setInstance(new RPCServiceImpl()); Server server=builder.build();
server.start(); //开启服务
}
}

运行结果:

七、常见问题分析

7.1.HDFS可不可以用来做网盘

答案:不可以,
网盘只存储,不用做分析,hdfs在增加节点,同时也加大了分析能力,主要是大容量存储之上的数据分析

1、容量成本太高,2、文件大小不确定,如果存大量小文件会造成很大的浪费 3、相对于网盘来说,文件读写的效率低  4、只适合一次写入,多次读取的操作

5、hdfs不支持文件内容修改,可支持往文件尾部追加内容。

7.2 HDFS大量小文件存储

1、对于待上传的文件,先将小文件合并为一个大文件再上传,利用SequenceFile、MapFile、Har等方式归档小文件,这个方法的原理就是把小文件归档起来管理,HBase就是基于此的。对于这种方法,如果想找回原来的小文件内容,那就必须得知道与归档文件的映射关系。
2、如果对于已经上传了的文件,需要进行合并的话,我们可以使用Map-redure来进行归档。
3、BlueSky解决方案,以一种two-level prefetching机制以提高小文件读取效率,即索引文件预取和数据文件预取。索引文件预取是指当用户访问某个文件时,该文件所在的block对应的索引文件被加载到内存中,这样,用户访问这些文件时不必再与namenode交互了。数据文件预取是指用户访问某个文件时,将该文件所在课件中的所有文件加载到内存中,这样,如果用户继续访问其他文件,速度会明显提高。



HDFS基本原理及数据存取实战的更多相关文章

  1. 分布式文件系统HDFS,大数据存储实战(一)

    本文进行了以下工作: OS中建立了两个文件,文件中保存了几组单词. 把这两个文件导入了hadoop自己的文件系统. 介绍删除已导入hadoop的文件和目录的方法,以便万一发生错误时使用. 使用列表命令 ...

  2. 云计算分布式大数据Hadoop实战高手之路第七讲Hadoop图文训练课程:通过HDFS的心跳来测试replication具体的工作机制和流程

    这一讲主要深入使用HDFS命令行工具操作Hadoop分布式集群,主要是通过实验的配置hdfs-site.xml文件的心跳来测试replication具体的工作和流程. 通过HDFS的心跳来测试repl ...

  3. 大数据开发实战:HDFS和MapReduce优缺点分析

    一. HDFS和MapReduce优缺点 1.HDFS的优势 HDFS的英文全称是 Hadoop Distributed File System,即Hadoop分布式文件系统,它是Hadoop的核心子 ...

  4. 大数据开发实战:Spark Streaming流计算开发

    1.背景介绍 Storm以及离线数据平台的MapReduce和Hive构成了Hadoop生态对实时和离线数据处理的一套完整处理解决方案.除了此套解决方案之外,还有一种非常流行的而且完整的离线和 实时数 ...

  5. 王家林的“云计算分布式大数据Hadoop实战高手之路---从零开始”的第十一讲Hadoop图文训练课程:MapReduce的原理机制和流程图剖析

    这一讲我们主要剖析MapReduce的原理机制和流程. “云计算分布式大数据Hadoop实战高手之路”之完整发布目录 云计算分布式大数据实战技术Hadoop交流群:312494188,每天都会在群中发 ...

  6. 云计算分布式大数据Hadoop实战高手之路第八讲Hadoop图文训练课程:Hadoop文件系统的操作实战

    本讲通过实验的方式讲解Hadoop文件系统的操作. “云计算分布式大数据Hadoop实战高手之路”之完整发布目录 云计算分布式大数据实战技术Hadoop交流群:312494188,每天都会在群中发布云 ...

  7. Hadoop基础-HDFS安全管家之Kerberos实战篇

    Hadoop基础-HDFS安全管家之Kerberos实战篇 作者:尹正杰 版权声明:原创作品,谢绝转载!否则将追究法律责任. 我们都知道hadoop有很多不同的发行版,比如:Apache Hadoop ...

  8. 大数据开发实战:Hive优化实战2-大表join小表优化

    4.大表join小表优化 和join相关的优化主要分为mapjoin可以解决的优化(即大表join小表)和mapjoin无法解决的优化(即大表join大表),前者相对容易解决,后者较难,比较麻烦. 首 ...

  9. 大数据开发实战:Hive表DDL和DML

    1.Hive 表 DDL 1.1.创建表 Hive中创建表的完整语法如下: CREATE [EXTERNAL] TABLE [IF NOT EXISTS]  table_name [ (col_nam ...

随机推荐

  1. C++ STL基本容器使用

    1:关联容器和顺序容器 c++中有两种类型的容器:顺序容器和关联容器,顺序容器主要有:vector.list.deque等.其中vector表示一段连续的内存地址,基于数组的实现,list表示非连续的 ...

  2. Redis Cluster 4.0 on CentOS 6.9 搭建

    集群简介 Redis 集群是一个可以在多个 Redis 节点之间进行数据共享的设施(installation). Redis 集群不支持那些需要同时处理多个键的 Redis 命令, 因为执行这些命令需 ...

  3. 线程的同步控制(Synchronization)

    临界区(Critical Sections) 摘要 临界区(Critical Section) 用来实现"排他性占有".适合范围时单一进程的各线程之间. 特点 一个局部对象,不是一 ...

  4. vue的入门/简介

    vue 特点 1. 响应的数据绑定/响应式编程  2. 组件化 vue优点 1. 轻量级的框架  2. 简单易学 3. 双向数据绑定 4. 组件化 5. 视图,数据,结构分离 6. 虚拟DOM 7. ...

  5. 典型分布式系统分析之MapReduce

    在 <分布式学习最佳实践:从分布式系统的特征开始(附思维导图)>一文中,提到学习分布式系统的一个好方法是思考分布式系统要解决的问题,有哪些衡量标准,为了解决这些问题:提出了哪些理论.协议. ...

  6. jenkins实战(一):war安装及插件安装

    一:整体介绍 以下摘自维基百科: Jenkins是一个用Java编写的开源的持续集成工具.在与Oracle发生争执后,项目从Hudson项目复刻. Jenkins提供了软件开发的持续集成服务.它运行在 ...

  7. BZOJ4894 天赋

    Description 小明有许多潜在的天赋,他希望学习这些天赋来变得更强.正如许多游戏中一样,小明也有n种潜在的天赋,但有 一些天赋必须是要有前置天赋才能够学习得到的.也就是说,有一些天赋必须是要在 ...

  8. [AHOI2012]铁盘整理

    题目描述 输入输出格式 输入格式: 共两行.第一行为铁盘个数N(1<=N<=50),第二行为N个不同的正整数,分别为从上到下的铁盘的半径R.(1<=R<=100) 输出格式: ...

  9. POJ 2289(多重匹配+二分)

    POJ 2289(多重匹配+二分) 把n个人,分到m个组中.题目给出每一个人可以被分到的那些组.要求分配完毕后,最大的那一个组的人数最小. 用二分查找来枚举. #include<iostream ...

  10. Codeforces Round #402 (Div. 1)

    A题卡壳了,往离线倒着加那方面想了会儿,后来才发现方向错了,二十多分钟才过掉,过了B后做D,想法好像有点问题,最后只过两题,掉分了,差一点回紫. AC:AB Rank:173 Rating:2227- ...