美文网首页
Hadoop之HDFS

Hadoop之HDFS

作者: 高默思 | 来源:发表于2019-03-29 09:16 被阅读0次

    本篇文章主要介绍分布式文件系统HDFS,常用的操作HDFS的命令 以及对应的JAVA API

    Hadoop分布式文件系统(HDFS)

    当数据集的大小超过一台独立的物理计算机的存储能力是,有必要对它进行分区并储存多若干单独的计算器上,管理网络中跨多台计算机储存的文件系统称为分布式文件系统,在Hadoop集群中的分布式文件系统称为Hadoop分布式文件系统,简称HDFS。

    HDFS特性

    HDFS以流式数据访问模式来存储超大文件,运行与商业硬件集群上

    • 超大文件
      存储在HDFS的文件可以有 几百MB,几百GB,甚至几百TB的大文件
    • 流式访问数据
      HDFS支持的 一次写入,多次读取是最高效的访问模式,文件系统的数据集通常一次从数据源写入或者一次复制数据源的数据,接着长时间的在此数据集上多次读取数据进行分析。
    • 商用硬件
      Hadoop并不需要部署在 昂贵且高可用的硬件上,它设计运行在各种商用硬件(普通硬件)的集群上面。虽然节点的故障率会增减,但是HDFS遇到故障时,被设计成能够继续运行且不让用户察觉到明显的中断。

    HDFS概念

    • 数据块
      计算机中,每个磁盘都有默认的磁盘块大小,这是磁盘进行数据读写的最小单位,一个文件写入磁盘,都是以一个一个磁盘块进行存储。每个磁盘块的大小为512字节。

      而这些在HDFS中,也有也有块(block)的概念,默认大小为128MB,HDFS上的文件会被分成多个块,这些块会分散存储在不同的节点上面,在HDFS中如果一个文件的大小为1MB,它不会占据整个块的容量,它只会占有1MB的磁盘空间,而不是128MB的磁盘空间。就是说 HDFS中小于一个块大小的文件不会占据整个块的空间。

    • namenode
      HDFS集群中有两类节点 管理节点-工作节点,即一个namenode(管理节点)和多个datanode(工作节点),namenode管理文件系统的命名空间,它维护着文件系统树及整棵树内所有的文件和目录,这两个文件会永久的保存在namenode节点的本地磁盘上,同时还会在该节点的内存中维护这两个文件的信息。

    • datanode
      datanode是文件系统的工作节点,它们根据需要存储并检索数据块,接受客户端或者nameode调用,并且定期向namenode发送它们存储的块的列表信息(简称:心跳检测)

    HDFS读写流程图
    • HDFS高可用
      在HDFS中namenode节点是一个重要的节点,如果这个节点发生故障,将会导致整个文件系统的崩溃,在namenode节点存储着文件系统的整个文件树。namenode两种高可用方式

      第一种机制是备份那些组成文件系统元数据持久状态的文件。Hadoop可以通过配置 使namenoded在多个文件系统上保存元数据的持久状态,这些写操作是实时同步的,且原子操作。但是这种机制还是不能避免如果namenode节点挂掉,整个文件系统不能正常运行。需要在重新启动一个namenode节点再把备份的元数据导入,然后才能复原

      第二种机制是运行一个辅助的namenode,但它不能被用作namenode,这个辅助的namenode的重要作用是定期合并编辑日志和命名空间镜像,以防止编辑日志过大。辅助的namenode一般在一个单独的节点上运行。当原namenode节点挂掉后,辅助namenode会将命令空间镜像的副本启动。来替代原namenode节点。但是辅助namenode的命名空间镜像的状态总是滞后于原namenode节点,所以会丢失部分数据,这种情况下会把第一种机制下备份的元数据(也就是丢失部分)复制到辅助namenode节点。这样就保证了辅助namenode和原namenode一样。

    HDFS的命令行接口

    首先要在本地部署Hadoop,并启动。本地部署Hadoop可以查看下面这篇文章
    Windos上本地部署Hadoop
    相关配置文件解释
    core-default.xml
    hdfs-default.xml
    mapred-default.xml
    yarn-default.xml

    在浏览器中 输入http://localhost:50070 打开Hadoop的UI界面

    Hadoop的UI界面

    HDFS命令行的通用格式
    hadoop fs -[命令] [路径]
    打开cmd 在HDFS中新建一个文件夹
    hadoop fs -mkdir /data


    将本地文件导入到HDFS文件系统中去 第一个路径是本地文件路径,第二个是HDFS路径
    hadoop fs -put C:\Users\Yong\Desktop\cite75_99.txt /data

    HDFS 更多命令可以查看
    HDFS Shell 命令大全

    HDFS的JAVA接口

    在java中把HDFS文件系统抽象成一个Filesystem的抽象类,DistributedFileSystem是这个抽象类的具体实现。在使用HDFS java API的时候需要指定HDFS的接入地址,也就是namenode节点开放的提供给客户端使用的地址和端口号

    import org.apache.hadoop.conf.Configuration;
    import org.apache.hadoop.fs.FSDataInputStream;
    import org.apache.hadoop.fs.FSDataOutputStream;
    import org.apache.hadoop.fs.FileSystem;
    import org.apache.hadoop.fs.Path;
    import org.apache.hadoop.io.IOUtils;
    import org.apache.hadoop.util.Progressable;
    import org.junit.Before;
    import org.junit.Test;
    import java.io.*;
    import java.net.URI;
    /**
     * @Description: HDFS API操作
     * @Author: Caoyong
     * @Date: 2019/3/28 15:56
     */
    public class HDFSApi {
    
        /**
         * namenode节点的地址和HDFS开放的端口
         */
        public static final String HDFS_PATH = "hdfs://localhost:9000";
        /**
         * HDFS操作对象
         */
        private FileSystem fileSystem;
        /**
         * 封装了客户端或服务端的配置
         */
        private Configuration configuration;
        /**
         * 初始化
         * @throws Exception
         */
        @Before
        public void setFileSystem() throws Exception {
           configuration = new Configuration();
           fileSystem = FileSystem.get(new URI(HDFS_PATH),configuration);
        }
    
    • 添加文件夹
        @Test
        public void createDirectory() throws IOException {
            fileSystem.mkdirs(new Path("/yong/data"));
        }
    
    • 写数据
    public void writeHDFS() throws Exception {
            String localPath = "C:\\Users\\Yong\\Desktop\\data.txt";
            String writePath = "/yong/data/data.txt";
    
            InputStream in = new BufferedInputStream(new FileInputStream(localPath));
            FSDataOutputStream out = fileSystem.create(new Path(writePath), new Progressable() {
                public void progress() {
                    /**
                     * Progressable 给写入数据提供写入进度提示 每次写入1024个字节就会打印一个.
                     */
                    System.out.print(".");
                }
            });
            /**
             * 第一个参数:表示输入流
             * 第二个参数:表示输出流
             * 第三个参数:表示缓冲区大小
             * 第四个参数:结束是否自动关闭输入输出流
             */
            IOUtils.copyBytes(in,out,1024,true);
        }
    

    通过FileSystem对象的create()方法,传递路径参数以及进度提示参数,打开HDFS文件系统的输入流FSDataOutputStream对象。通过IOUtils工具类将数据出入到HDFS文件系统的指定位置。

    • 读数据
    public void readHDFS() throws IOException {
            String readPath = "/yong/data/data.txt";
            FSDataInputStream in = fileSystem.open(new Path(readPath));
            IOUtils.copyBytes(in,System.out,1024,false);
            /**
             * seek(int index)重新设置读取流位置
             */
            in.seek(0);
            System.out.println("===============================");
            IOUtils.copyBytes(in,System.out,1024,true);
        }
    

    通过FileSystem对象的open()方法,传递路径参数,打开HDFS文件系统的输出流FSDataInputStream对象。通过IOUtils工具类将HDFS文件系统的指定位置的数据输出。调用seek()方法重新设置读取文件的位置

    • 删除
    public void deleteFile() throws IOException {
            /**
             * 最后一个参数:表示如果删除是目录设置true 删除文件设置false
             */
            fileSystem.delete(new Path("/yong/data/data.txt"),false);
        }
    

    Hadoop API的更多方法可以查看FileSystem

    相关文章

      网友评论

          本文标题:Hadoop之HDFS

          本文链接:https://www.haomeiwen.com/subject/xuykbqtx.html