Hadoop 分布式存储系统介绍

Hadoop 分布式存储(hdfs)系统介绍

hadoop组成

hadoop 集群主要做了两件事: 分布式存储(hdfs) 和分布式计算(map-reduce)。本文主要对hadoop 分布式存储理解做一个记录 帮助以后快速记忆 。

分布式存储(hdfs)

分为 hadoop 1.x 和 hadoop 2.x

hadoop1.x 存储系统

在这里插入图片描述

NameNode :
1,负责接收用户的请求
2,维护一套账本 记录所有的文件存储位置。

存储系统的本质操作:
在这里插入图片描述

在机房中就是这样:
在这里插入图片描述

Switch是交换机(路由器)、Rack代表机房里的一个机柜,每个机柜里都有很多台服务器,称之为节点。

hadoop 2.x 存储系统

1,1.x 有一个问题就是 NameNode 不能扩展 万一宕机 账本没有了 整个系统就崩溃了 2.x 可以配置多个NameNode .
2, 单个NameNode 虽然账本很小 但是内存也是有限的。
在这里插入图片描述

存储账本原理

账本组成有: fsimage , edits
fsimage 是整个系统的账本信息
edits 你运行的时候 所做的操作记录

1,hdfs 启动的时候 首先加载 fsimage 进入内存
2,客户端对hdfs 的操作信息会写入 edits 。 当系统崩溃的时候 下一次启动 hdfs 先恢复edits 里面的操作 。如果正常结束 hdfs 这里面的所有记录 应该为空。

3,随着edits内容增大,就需要在一定时间点和fsimage合并。

在这里插入图片描述

左边是NameNode 右边方块是 SecondNameNode .

SecondNameNode 是可以配置的 主要任务是帮助NameNode 上的账本完成不定时的合并 。
在这里插入图片描述

secondarynamenode在合并edits和fsimage时需要消耗的内存和namenode差不多,所以一般把namenode和secondarynamenode放在不同的机器上。
fs.checkpoint.period: 默认是一个小时(3600s)
fs.checkpoint.size: edits达到一定大小时也会触发合并(默认64MB)

JournalNodes

两个NameNode为了数据同步,会通过一组称作JournalNodes的独立进程进行相互通信。当active状态的NameNode的命名空间有任何修改时,会告知大部分的JournalNodes进程。standby状态的NameNode有能力读取JNs中的变更信息,并且一直监控edit log的变化,把变化应用于自己的命名空间。standby可以确保在集群出错时,命名空间状态已经完全同步了

常用命令操作

本节将讲解HDFS中,常见的命令行操作。HDFS与我们传统的文件系统类似,都可以存储文件,查看文件的内容,删除文件,并且文件也有着权限的概念。事实上,HDFS也借鉴了Linux文件系统的目录树结构和权限系统。

一、基本操作

启动:

start-all.sh

停止:

stop-all.sh

1、创建目录

hadoop fs -mkdir /hdfs #在根目录下创建hdfs文件夹

2、查看目录

hadoop fs -ls / #列出跟目录下的文件列表
drwxr-xr-x - root supergroup 0 2016-03-05 00:06 /hdfs

3、级联创建目录

hadoop fs -mkdir -p /hdfs/d1/d2

4、级联列出目录

hadoop fs -ls -R /
drwxr-xr-x - root supergroup 0 2016-03-05 00:10 /hdfs
drwxr-xr-x - root supergroup 0 2016-03-05 00:10 /hdfs/d1
drwxr-xr-x - root supergroup 0 2016-03-05 00:10 /hdfs/d1/d2

5、上传本地文件到HDFS

echo “hello hdfs” >>local.txt
hadoop fs -put local.txt /hdfs/d1/d2

6、查看HDFS中文件的内容

hadoop fs -cat /hdfs/d1/d2/local.txt
hello hdfs

7、下载hdfs上文件的内容

hadoop fs -get /hdfs/d1/d2/local.txt
8、删除hdfs文件

hadoop fs -rm /hdfs/d1/d2/local.txt
Deleted /hdfs/d1/d2/local.txt

9、删除hdfs中目录

hadoop fs -rmdir /hdfs/d1/d2

10、修改文件的权限

hadoop fs -ls /hdfs
drwxr-xr-x - root supergroup 0 2016-03-05 00:21 /hdfs/d1 #注意文件的权限
hadoop fs -chmod 777 /hdfs/d1
drwxrwxrwx - root supergroup 0 2016-03-05 00:21 /hdfs/d1 #修改后

11、修改文件所属的用户

hadoop fs -chown admin /hdfs/d1 #修改文件所属用户为admin
hadoop fs -ls /hdfs
drwxrwxrwx - admin supergroup 0 2016-03-05 00:21 /hdfs/d1

12、修改文件的用户组

hadoop fs -chgrp admin /hdfs/d1
hadoop fs -ls /hdfs
drwxrwxrwx - admin admin 0 2016-03-05 00:21 /hdfs/d1

Java 代码实现

配置文件

<!--hadoopHDFS依赖--> 
<dependency>
            <groupId>org.apache.hadoop</groupId>
            <artifactId>hadoop-common</artifactId>
            <version>2.6.0-cdh5.4.7</version>
        </dependency>
 <dependency>
            <groupId>org.apache.hadoop</groupId>
            <artifactId>hadoop-hdfs</artifactId>
            <version>2.6.0-cdh5.4.7</version>
 </dependency> 
<!--hadoop使用到了jdk自带的tools.jar-->
 <dependency>
    <groupId>jdk.tools</groupId>
    <artifactId>jdk.tools</artifactId>
    <version>1.7</version>
    <scope>system</scope>
    <systemPath>${JAVA_HOME}/lib/tools.jar</systemPath>
</dependency>
 
  <repositories>
        <repository>
            <id>cloudera</id>
            <url>https://repository.cloudera.com/artifactory/cloudera-repos/</url>
        </repository>
    </repositories>

获取对象

Hadoop提供FileSystem类用于表示HDFS文件系统,我们对HDFS所有的操作都是要基于这个类来进行完成。因此我们首先要做的就是获取这个类的实例。

public class HDFSAPI {
    public static String nameNodeUrl="hdfs://115.28.65.149:9000";
    public static Configuration configuration=new Configuration();
    public static FileSystem fileSystem;
    
    @BeforeClass
    public static void beforeClass() throws Exception{
        Configuration configuration=new Configuration();
        configuration.set("fs.defaultFS", "hdfs://115.28.65.149:9000");
        URI uri = new URI(nameNodeUrl);
        String user="root";
        fileSystem=FileSystem.get(uri,configuration,user);
        System.out.println(fileSystem);
    }
    ...
 }

运行程序输出:

DFS[DFSClient[clientName=DFSClient_NONMAPREDUCE_-1459561864_1, ugi=root (auth:SIMPLE)]]

说明:

因为通过网络来进行访问,所以我们必须配置HDFS的网络路径,实际上就是我们hadoop集群中core-site.xml配置的fs.default.name项的值。我们通过Configuration类来进行设置。只不过配置项的名字改为"fs.defaultFS"。这里我们是通过字符串来指定配置项的名字,实际上,Hadoop还提供了2个类CommonConfigurationKeysPublicCommonConf和CommonConfigurationKeys两个类,这两个类中包含了Hadoop客户端所有配置项的key和默认值,例如我们这里的"fs.defaultFS"就可以用CommonConfigurationKeysPublic.FS_DEFAULT_NAME_KEY 来指定。

我们使用FileSystem.get(uri,configuration,user);这个方法来获取FileSystem的实例,这里指定的user为root,实际上也可以不指定。主要是因为我在Linux系统上是通过root用户来启动hadoop集群的。这里显示指定root,那么我就有权限访问HDFS文件系统中的所有内容。如果不指定,就会以启动我们这个客户端的程序的身份去访问HDFS,由于笔者是在Windows操作系统上写的代码,用户名为Administer,那么可能就会有一些文件没有权限访问

创建文件夹

@Test
    public void mkdirs() throws IOException{
        Path path=new Path("/hdfs/javaapi");
        final boolean exists = fileSystem.exists(path);
        System.out.println(exists);//创建前
        if(!exists){
            fileSystem.mkdirs(path);
        }
        System.out.println(fileSystem.exists(path));//创建后
    }

运行程序,控制台输出

false
true

说明:

Hadoop使用PATH对象表示HDFS文件中的路径,因为是仿照Linux系统的路径命名习惯,所以我们传入的路径是"/hdfs/javaapi"。在创建文件夹文件夹之前,我们依然要判断是否存在,不存在才可以创建,否则会抛出异常。

上传文件

@Test
    public void uploadFile() throws Exception{
        String uploadPath="/hdfs/javaapi/upload.txt";//文件保存路径
        String content="test upload file";//文件内容
        boolean overwrite=true;//如果文件存在就覆盖
        final Path hdfsPath = new Path(uploadPath);
        FSDataOutputStream out=fileSystem.create(hdfsPath, overwrite);
        boolean close=true;//上传成功关闭输入流和输出流
        int bufferSize=1024;//缓冲大小
        ByteArrayInputStream in = new ByteArrayInputStream(content.getBytes());//输入流
        IOUtils.copyBytes(in, out, bufferSize,close);
        System.out.println(fileSystem.exists(hdfsPath));//判断文件是否上传到HDFS上
    }

运行程序,控制台输出:

true
说明:

HDFS是提供了FSDataOutputStream对象来表示输出流,对应的有FSDataInputStream表示输入流。因为HSFS是需要通过流式的方式进行操作,所以我们把上传的内容content转换成了输入流。IOUtils是hadoop提供的一个工具类,帮我们从输入流往输出流中写数据。

下载文件

@Test
    public void downloadFile() throws Exception {
        String  downloadPath = "/hdfs/javaapi/upload.txt";
        FSDataInputStream inputStream = fileSystem.open(new Path(downloadPath));
        IOUtils.copyBytes(inputStream, System.out, 1024, true);
    }

运行程序,控制台输出

test upload file
说明:

FileSystem的open方法返回的是一个FSDataInputStream对象,表示指定文件的输入流。此处我们依然使用了工具类IOUtils,将获取到的内容显示在了控制台上(通过指定输出流为System.out).

递归列出文件夹中所有内容(包含子目录)

@Test
    public void recursive() throws IOException {
        FileStatus[] listStatus = fileSystem.listStatus(new Path("/hdfs"));
        for (FileStatus fileStatus : listStatus) {
                listFiles(fileStatus);
        }
    }
 
   private void listFiles(FileStatus fileStatus) throws IOException {
        Path path = fileStatus.getPath();
        System.out.println(path);
        if (!fileStatus.isDirectory()) {// 如果不是目录
            
             FsPermission permission = fileStatus.getPermission(); 
             String owner = fileStatus.getOwner(); 
             short replication = fileStatus.getReplication(); 
             long len = fileStatus.getLen();
            System
             .out.println("path:"+path+",permission:"+permission+",replication:"
             +replication+",owenr:"+owner+",size:"+len);
            
        } else {// 如果是目录
            FileStatus[] listStatus = fileSystem.listStatus(path);
            for (FileStatus childStatus : listStatus) {
                listFiles(childStatus);
            }
        }
    }

运行程序,控制台输出:

hdfs://115.28.65.149:9000/hdfs/d1
hdfs://115.28.65.149:9000/hdfs/javaapi
hdfs://115.28.65.149:9000/hdfs/javaapi/upload.txt
path:hdfs://115.28.65.149:9000/hdfs/javaapi/upload.txt,permission:rw-r–r–,replication:3,owenr:root,size:16
说明:

FileStatus对象用于表示HDFS中文件的元数据(包含文件的路径,文件大小、权限、备份数等信息)。

fileSystem.listStatus(new Path(“/hdfs”))方法的返回值是FileStatus[]数组,表示的是/hdfs目录下所有的文件/文件夹的源信息。

通过fileStatus.getPath()f方法,我们可以获得一个文件的访问路径。通过fileStatus.isDirectory(),我们可以判断当前路径是文件还是文件夹。

FsPermission对象表示的是一个文件的权限信息,通过fileStatus.getPermission()方法获得。

文件的备份数,通过fileStatus.getReplication()获得,返回值是一个short整数。

文件的所有者通过fileStatus.getOwner()f方法获得。

参考文献

http://www.tianshouzhi.com/api/tutorials/hadoop/132

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值