【Hadoop】HDFS入门解析

一、Hadoop三大组件

  • 1.HDFS 分布式文件存储系统
  • 2.MapReduce 分布式离线计算框架
  • ​3.Yarn Hadoop资源调度器

1.HDFS

HDFS的设计特点是:

1、大数据文件,非常适合上T级别的大文件或者一堆大数据文件的存储,如果文件只有几个G甚至更小就没啥意思了

2、文件分块存储,HDFS会将一个完整的大文件平均分块存储到不同计算器上,
   它的意义在于读取文件时可以同时从多个主机取不同区块的文件,多主机读取比单主机读取效率要高得多得都。

3、流式数据访问,一次写入多次读写,这种模式跟传统文件不同,
   它不支持动态改变文件内容,而是要求让文件一次写入就不做变化,要变化也只能在文件末添加内容。

4、廉价硬件,HDFS可以应用在普通PC机上,这种机制能够让给一些公司用几十台廉价的计算机就可以撑起一个大数据集群。

5、硬件故障,HDFS认为所有计算机都可能会出问题,为了防止某个主机失效读取不到该主机的块文件,
   它将同一个文件块副本分配到其它某几个主机上,如果其中一台主机失效,可以迅速找另一块副本取文件
管理者:NameNode
  • 1)作用
    • 1.维护整个文件系统的元数据/名字空间/目录树
    • 2.维护每一个路径/文件所对应的block块信息
    • 3.维护DataNode的心跳日志
    • 4.客户端与DataNode之间的桥梁
  • 2)NameNode元数据持久化的2种形式
    • 1.EditsLog(日志文件)
      对于文件系统的每一次更改,例如,增加文件,删除文件等操作都会被写入Edit Log
    • 2.FsImage(镜像文件)
      ​ 集群最近一次关机前的状态(HDFS目录树),NameNode在启动时会加载镜像文件的信息
    • eg:持久化数据中不包括Block所在的节点列表,及文件的Block分布在集群中的哪些节点上,这些信息 是在系统重启的时候,在安全模式下重新构建(通过DataNode做心跳,汇报的Block信息)
  • 3)NameNode启动过程发生了什么?
    • 1、从硬盘读取FsImage 和EditLog文件
    • 2、将EditLog文件中的所有操作信息写入FsImage中,产生一个新的FsImage文件,这一操作被称为 checkpoint
    • 3、DataNode汇报心跳信息
    • 4、产生一个新的空的EditLog文件
  • 4)NameNode单点故障解决方案
    在HDFS中,Namenode可能成为集群的单点故障,Namenode不可用时,整个文件系统是不可用的。 HDFS针对单点故障提供了以下2种解决机制:
    • 1、备份持久化元数据
      ​ 将文件系统的元数据同时写到多个文件系统, 例如同时将元数据写到本地文件系统及NFS。这些备份操作都是同步的、原子的
    • 2、Secondary NameNode
      ​ Secondary节点定期合并主NameNode的namespace image和edit log, 避免edit log过大,通过创建 检查点 checkpoint 来合并;它会维护一个合并后的namespace image副本,可用于在Namenode完全崩 溃时恢复数据。
      Secondary Namenode通常运行在另一台机器,因为合并操作需要耗费大量的CPU和内存。其数据落后 于Namenode,因此当Namenode完全崩溃时,会出现数据丢失。 通常做法是拷贝NFS中的备份元数据 到Second Namenode,将其作为新的主Namenode
      ​在HA(High Availability高可用性)中可以运行一个Hot Standby,作为热备份,在Active Namenode故障之后,替代原有Namenode成为Active Namenode。
工作者:DataNode
  • 1)作用
    • 1.负责数据的存储与读写
    • 2.周期性的向NameNode做心跳报告(节点状态、数据的状态和校验和)
    • 3.执行数据的流水线复制
辅助管理者:SecondaryNameNode
  • 1)作用
    • 合并NameNode的Edits log和fsimage成新的fsimage,防止Edits log过大,加快集群二次启动的速度
  • 2)工作流程
    日志与镜像的定期合并总共分五步:
    • 1.SecondaryNameNode通知NameNode准备合并文件,此时NameNode节点产生edits.new,之后的所有操作日志写入edits.new中
    • 2.SecondaryNameNode通过http get方式获取NameNode的fsimage与edits文件(在 SecondaryNameNode的current同级目录下可见到 temp.check-point或者previous-checkpoint目录,这些目录中存储着从namenode拷贝来的镜像文件)
    • 3.SecondaryNameNode将edits和fsimage加载到内存中进行合并操作,产生一个新的fsimage文件fsimage.ckpt
    • 4.SecondaryNameNode用http post方式发送fsimage.ckpt至NameNode
    • 5.NameNode将fsimage.ckpt与edits.new文件分别重命名为fsimage与edits,然后更新fstime,整个checkpoint过程到此结束。 在新版本的hadoop中(hadoop0.21.0),SecondaryNameNode两个作用被两个节点替换, checkpoint node与backup node. SecondaryNameNode备份由三个参数控制fs.checkpoint.period控制周期,fs.checkpoint.size控制日志文件超过多少大小时合并, dfs.http.address表示http地址,这个参数在SecondaryNameNode为单独节点时需要设置。
  • 3)触发secondarynameNode合并文件的条件
    • 1、时间维度, 默认一小时合并一次 ; 自定义需要添加如下配置进行修改

      <property>
      	<name>dfs.namenode.checkpoint.period</name>
      	<value>3600</value>
      </property>
      
    • 2、次数维度,默认100万次合并一次;自定义需要添加如下配置进行修改

      <property>
      	<name>dfs.namenode.checkpoint.txns</name>
      	<value>1000000</value>
      </property>
      

HDFS副本机制:

eg: Hadoop 视硬件设备经常损坏为常态,为了防止硬件损坏导致系统不可用,所以构建多副本机制
  • 1)、第一份数据来源于用户的客户端所在节点,如果客户端在集群外,则按照一定的机制(cpu、内存、IO 使用率和节点磁盘剩余容量)随机选择一个节点
  • 2)、第二份数据存放在与第一份副本在同一个机架,不同的节点,按照一定的机制选取一个节点进行存放
  • 3)、第三份副本存放在与第一、第二副本不在同一机架,且逻辑距离最近的机架上,按照一定的机制,选择一个节点进行存放

HDFS机架感知:

默认情况下,Hadoop的机架感知是没有被启用的,若要将Hadoop机架感知的功能启用,只需要在NameNode所在节点的的hdfs-site.xml配置文件中配置一个选项:

<property>
	<name>topology.script.file.name</name>
	<value>python脚本路径</value>
</property>

这个配置选项的value指定为一个可执行程序,通常为一个python脚本,该脚本接受一个参数,输出一个值;接受的参数通常为某台DataNode机器的ip地址,而输出的值通常为该ip地址对应的DataNode所在的rack,例如”/rack1”;Namenode启动时,会判断该配置选项是否为空,如果非空,则表示已经用机架感知的配置,此时NameNode会根据配置寻找该脚本,并在接收到每一个DataNode的heartbeat时,将该DataNode的ip地址作为参数传给该脚本运行,并将得到的输出作为该DataNode所属的机架,保存到内存的一个map中;


HDFS高级命令:

特定文件夹下的副本数可以设置、存储容量可以设置,存储的文件个数可以设置
  • 1)设置文件夹内文件的个数: hdfs dfsadmin -setQuota 50 /test(test本身算一个 所以test文件夹内最多有49个)
  • 2)清除文件数量限制 hdfs dfsadmin -clrQuota /test
  • 3)限制空间大小 hdfs dfsadmin -setSpaceQuota 100M /test (最多可以存储100M)
  • 4)清除空间限额 hdfs dfsadmin -clrSpaceQuota /test
  • 5)查看hdfs文件限额数量 hdfs dfs -count -q -h /test

如何将FsImage和Edits Log文件转换成XML进行查看?

  • FsImage数据的存放路径 :
<property>
	<name> dfs.namenode.name.dir</name>
	<value>FsImage存放路径</value>
</property>
  • Edits Log数据的存放路径 :
<property>
	<name> dfs.namenode.edits.dir</name>
	<value>Edits Log存放路径</value>
</property>
  • 将edits文件转换成XML
    hdfs oev -i edits_0000000000000000416-0000000000000000418 -p XML -o test001.xml
  • 将Fsimage文件转换成XML
    hdfs oiv -i fsimage_0000000000000000418 -p XML -o test002.xml

HDFS写入数据流程

在这里插入图片描述
在这里插入图片描述

步骤:
  • 1.客户端通过调用FileSystem对象的create()来创建文件
  • 2.客户端发起文件写入请求,通过RPC与NameNode建立通讯,NameNode检查目标文件,返回是否可以上传
  • 3.client请求第一个block该传输到哪些DataNode服务器上
  • 4.NameNode根据配置文件中指定的备份数量及机架感知原理进行文件分配,返回可用的DataNode的地址列表
  • 5.Client 端请求地址列表中最近的一个DataNode,该DataNode再请求其他DataNode,构成pipeline管道
  • 6.Client 往pipeline管道里写大小为64K的packet数据,packet数据通过pipeline管道不断流向对应的DataNode节点上进行存储,然后在pipeline管道上逐个返回ack,最终由pipeline中第一个DataNode节点将pipeline ack发送给client
  • 6.当一个block块写入完成之后,客户端继续向NameNode获取下一个block块的位置信息,继续写入
  • 7.当把所有块写入完成后,Client关闭输出流
  • 8.最后客户端告知NN节点写入成功

HDFS读取数据流程

在这里插入图片描述
在这里插入图片描述

步骤:
  • 1.Client向NameNode发起RPC请求,来确定请求文件block所在的位置;
  • 2.NameNode会视情况返回文件的部分或者全部block列表,对于每个block,NameNode 都会返回含有该 block副本的 DataNode 地址; 这些返回的 DN 地址,会按照集群拓扑结构得出 DataNode 与客户端的距离,然后进行排序,排序两个规则:网络拓扑结构中距离 Client 近的排靠前;心跳机制中超时汇报的 DN 状态为 STALE,这样的排靠后
  • 3.Client选取排序靠前的DataNode来读取block,如果客户端本身就是DataNode,那么将从本地直接获取数据(短路读取特性)
  • 5.当读完一批的 block块后,若文件读取还没有结束,客户端会继续向NameNode 获取下一批的 block 列表,继续读取(读取完一个block都会进行checksum验证,如果读取DataNode时出现错误,客户端会通知NameNode,然后再从下一个拥有该block副本的DataNode继续读)
  • 6.所有block块读取完成后,Client关闭输入流,并将读取来所有的 block块合并成一个完整的最终文件

读写过程,数据完整性如何保持?

  • 通过校验和。因为每个chunk中都有一个校验位,一个个chunk构成packet,一个个packet最终形成 block,故可在block上求校验和。

  • HDFS 的client端即实现了对 HDFS 文件内容的校验和 (checksum) 检查。当客户端创建一个新的HDFS文件时候,分块后会计算这个文件每个数据块的校验和,此校验和会以一个隐藏文件形式保存在同一个 HDFS 命名空间下。当client端从HDFS中读取文件内容后,它会检查分块时候计算出的校验和(隐藏文件里)和读取到的文件块中校验和是否匹配,如果不匹配,客户端可以选择从其他 DataNode 获取该数据块的副本。

  • 数据写入之后进行数据首次校验,文件系统周期性进行校验,防止数据丢失。
    读取数据之前进行数据校验,若两个校验相同,那么表示数据没有丢失,开始读取数据。
    若两个校验不相同,那么表示数据有部分丢失,换到其他节点(相同副本的节点)读取数据。


HDFS优点

  • 1.高容错性
    • a.数据自动保存多个副本;通过增加副本的形式,提高容错性
    • b.某一个副本丢失以后,可以自动恢复,这是由 HDFS 内部机制实现的
  • 2.适合批处理
    • a.计算向数据移动
    • b.数据位置暴露给计算框架
  • 3.适合大数据处理
    • a.处理数据达到 GB、TB、甚至PB级别的数据
    • b.能够处理百万规模以上的文件数量
    • c.能够处理10K节点的规模
  • 4.流式文件访问
    • a.一次写入,多次读取;文件一旦写入不能修改,只能追加
    • b.能保证数据的一致性
  • 5.可构建在廉价机器上
    • a.通过多副本机制,提高可靠性
    • b.提供了容错和恢复机制

HDFS缺点

  • 1.不擅长低延时数据访问
    由于hadoop针对高数据吞吐量做了优化,牺牲了获取数据的延迟,所以对于低延迟访问数据的业务需求不适合HDFS。
  • 2.不擅长大量小文件存储
    存储大量小文件的话,它会占用 NameNode大量的内存来存储文件、目录和块信息。这样是不可取的,因为NameNode的内存总是有限的。
  • 3.不支持并发写入
    同一时间内,只能有一个用户执行写操作
  • 4.不支持文件随机修改
    仅支持数据末尾 append(追加),不支持文件的随机修改。

HDFS的安全模式

安全模式是HDFS的一种工作状态,处于安全模式的状态下,只向客户端提供文件的只读视图,不接受对命名空间的修改;同时NameNode节点也不会进行数据块的复制或者删除,如:副本的数量小于正常水平。

NameNode启动时,首先fsimage载入内存,并执行编辑日志中的操作。一旦文件系统元数据建立成功,便会创建一个空的编辑日志。此时,NameNode开始监听RPC和Http请求。但是此时NameNode处于安全模式,只接受客户端的读请求。

在安全模式下,各个DataNode会向NameNode发送自身的数据块列表,当NameNode有足够的数据块信息后,便在30秒后退出安全模式,若NameNode发现数据节点过少会启动数据块复制过程(基本不会)

当hadoop的NameNode节点启动时,会进入安全模式阶段。在此阶段,DataNode会向NameNode上传他们数据块的列表,让NameNode得到数据块的位置信息,并对每个文件对应的数据块副本进行统计。当最小副本条件满足时,即:一定比例的数据块都到达最小副本数,系统会退出安全模式。而这需要一定的延迟时间。当最小的副本条件未达到要求时,就会对副本数不足的数据块安排DataNode进行复制,直到达到最小的副本数。而在安全模式下,系统会处于只读装态,NameNode不会处理任何数据块的复制和删除命令。

在启动一个刚刚格式化的HDFS时系统不会进入安全模式,因为没有数据块。

HDFS安全模式相关的命令

hadoop dfsadmin -safemode leave   强制NameNode退出安全模式
hadoop dfsadmin -safemode enter   进入安全模式
hadoop dfsadmin -safemode get     查看安全模式状态
hadoop dfsadmin -safemode wait    等待一直到安全模式结束

回收站

1)默认回收站

默认值fs.trash.interval=0,0表示禁用回收站,可以设置删除文件的存活时间。
默认值fs.trash.checkpoint.interval=0,检查回收站的间隔时间。
要求fs.trash.checkpoint.interval<=fs.trash.interval

2)启用回收站
修改core-site.xml,配置垃圾回收时间为1分钟。

<property>
	<name>fs.trash.interval</name>
	<value>1</value>
</property>

3)查看回收站

回收站在集群中的;路径:/user/用户名/.Trash/….

4)修改访问垃圾回收站用户名称
进入垃圾回收站用户名称,默认是 dr.who,修改为 zsy 用户

[core-site.xml]
<property>
  <name>hadoop.http.staticuser.user</name>
  <value>zsy</value>
</property>

5)通过程序删除的文件不会经过回收站,需要调用moveToTrash()才进入回收站

Trash trash = New Trash(conf);
trash.moveToTrash(path);

6)恢复回收站数据

hadoop fs -mv /user/zsy/.Trash/Current/user/zsy/input    /user/zsy/input

7)清空回收站

hdfs dfs -expunge

HDFS的常用基本命令

1.上传
bin/hadoop fs -put 本地文件 hdfs文件路径
示例:bin/hadoop fs -put ~/put/test.txt /

2.下载
bin/hadoop fs -get hdfs文件 本地文件路径
示例:bin/hadoop fs -get /test ~/get/

3.查看文件列表
bin/hadoop fs -ls 文件路径
示例:bin/hadoop fs -ls /

4.查看文件内容
bin/hadoop fs -cat hdfs文件
示例:bin/hadoop fs -cat /test.txt

5.创建目录

创建一级目录
bin/hadoop fs -mkdir /aaa

创建多级目录
bin/hadoop fs -mkdir -p /a/b/c/

6.删除目录
bin/hadoop fs -rmdir /aaa

7.删除文件
bin/hadoop fs -rm /test.txt
删除目录(非空)
bin/hadoop fs -rm -r /a//b/c

JavaAPI操作:

前提:添加Maven依赖,如下👇

<dependencies>
   <dependency>
        <groupId>org.apache.Hadoop</groupId>
        <artifactId>Hadoop-client</artifactId>
        <version>2.7.4</version>
    </dependency>
    <dependency>
        <groupId>org.apache.Hadoop</groupId>
        <artifactId>Hadoop-common</artifactId>
        <version>2.7.4</version>
    </dependency>
    <dependency>
        <groupId>org.apache.Hadoop</groupId>
        <artifactId>Hadoop-hdfs</artifactId>
        <version>2.7.4</version>
    </dependency>

    <dependency>
        <groupId>org.apache.Hadoop</groupId>
        <artifactId>Hadoop-mapreduce-client-core</artifactId>
        <version>2.7.4</version>
    </dependency>
</dependencies>
public class HDFSAPI {

    static Configuration conf = null;
    static FileSystem fs = null;
    static Double num1 = 0d;
    static Double num2 = 0d;

    static {
        conf = new Configuration();
        try {
            fs = FileSystem.get(new URI("hdfs://192.168.100.111:8020/"), conf);
        } catch (IOException e) {
            e.printStackTrace();
        } catch (URISyntaxException e) {
            e.printStackTrace();
        }
    }

    /**
     * TODO 关闭资源
     *
     * @throws IOException
     */
    public static void close() throws IOException {
        if (fs != null) {
            fs.close();
        }
        if (conf != null) {
            conf.clear();
        }
    }

    /**
     * 资源异常类
     */
    private static class ResoucesInitException extends Exception {
        public ResoucesInitException(String message) {
            super(message);
        }
    }

    /**
     * TODO 检查资源初始化是否正常
     *
     * @throws Exception
     */
    public static void checkResource() throws Exception {
        if (fs != null || conf != null) {
            throw new ResoucesInitException("资源初始化异常...");
        }
    }


    public static void main(String[] args) throws Exception {
        close();
    }

    
    /**
     * TODO 删除HDFS集群中的所有空文件和空目录
     *
     * @param path
     * @param flag 是否删除空文件夹, true or false
     * @throws IOException
     */
    public static void Demo03(String path, boolean flag) throws IOException {
        FileStatus[] fileStatuses = fs.listStatus(new Path(path));
        for (FileStatus fileStatus : fileStatuses) {
            if (fileStatus.isFile()) {
                if (fileStatus.getLen() == 0) {
                    fs.deleteOnExit(fileStatus.getPath());
                }
            }
        }
    }


    /**
     * TODO 删除某个路径下特定类型的文件,比如class类型文件,比如txt类型文件
     *
     * @param path
     * @param suffixType 后缀类型
     * @throws IOException
     */
    public static void Demo02(String path, String suffixType) throws IOException {
        FileStatus[] fileStatuses = fs.listStatus(new Path(path));
        for (FileStatus fileStatus : fileStatuses) {
            if (fileStatus.isFile()) {
                String fileName = fileStatus.getPath().getName();
                if (fileName.endsWith(suffixType)) {
                    fs.deleteOnExit(new Path(path + fileName));
                }
            }
        }
    }


    /**
     * TODO 编写程序统计出HDFS文件系统中文件大小小于HDFS集群中的默认块大小的文件占比
     *
     * @param path
     * @param flag 是否遍历子目录,true or false
     * @throws IOException
     */
    public static void Demo01(String path, boolean flag) throws IOException {
        FileStatus[] fileStatuses = fs.listStatus(new Path(path));
        for (FileStatus fileStatus : fileStatuses) {
            if (fileStatus.isFile()) {
                if (fileStatus.getLen() < 134217728) {
                    num1++;
                }
                num2++;
            } else {
                if (flag == true) {
                    listFile(fileStatus.getPath().toString(), true,true);
                }
            }
        }
    }


    /**
     * TODO 查看文件系统指定路径的文件或文件夹
     *
     * @param path 路径
     * @param flag 是否遍历子目录,true or false
     * @param flag2 是否打印当前路径的目录,true or false
     * @throws IOException
     * 1.查看当前路径的所有文件
     * 2.查看当前路径的所有文件和目录
     * 3.查看当前路径的所有文件和目录以及子文件、子目录
     * 4.查看当前路径的所有文件和目录的子文件(只查看文件)
     */
    public static void listFile(String path, boolean flag,Boolean flag2) throws IOException {
        FileStatus[] fileStatuses = fs.listStatus(new Path(path));
        for (FileStatus fileStatus : fileStatuses) {
            if (fileStatus.isFile()) {
                System.out.println(fileStatus.getPath());
            } else {
                if (flag == true) {
                    listFile(fileStatus.getPath().toString(), true,true);
                }
                if(flag2 == true){
                    System.out.println(fileStatus.getPath());
                }
            }
        }
    }


    /**
     * TODO hdfs上创建文件夹
     * @param dirNamePath  eg: /tmpDir or /tmpDir/one
     * @throws Exception
     */
    public static void mkdirs(String dirNamePath) throws Exception {
        boolean mkdirs = fs.mkdirs(new Path(dirNamePath));
    }

    /**
     * TODO hdfs文件上传
     *
     * @throws Exception
     */
    public static void putData(String filePath, String hdfsPath) throws Exception {
        fs.copyFromLocalFile(new Path(filePath), new Path(hdfsPath));
    }

    /**
     * TODO hdfs下载文件
     *
     * @throws Exception
     */
    public static void getData(String fileName, String localPath) throws Exception {
        fs.copyToLocalFile(new Path(fileName), new Path(localPath));
    }


    /**
     * @param filePath
     * @param flag
     * @throws Exception
     */
    public static void delData(String filePath,boolean flag) throws Exception {
        // deleteOnExit 执行成功后不会立即删除
        // delete 执行成功后会立即删除,如果别人正常使用该文件或目录,则删除不了
        fs.delete(new Path(filePath),flag);
    }

    /**
     * TODO 获取FileSystem的4种方式
     */
    //    第一种:
    public FileSystem getFileSystem1() throws URISyntaxException, IOException {
        Configuration configuration = new Configuration();
        FileSystem fileSystem = FileSystem.get(new URI("hdfs://mycluster:8020"), configuration);
        return fileSystem;
    }

    //    第二种
    public FileSystem getFileSystem2() throws URISyntaxException, IOException {
        Configuration configuration = new Configuration();
        configuration.set("fs.defaultFS", "hdfs://mycluster:8020");
        FileSystem fileSystem = FileSystem.get(new URI("/"), configuration);
        return fileSystem;
    }

    //    第三种
    public FileSystem getFileSystem3() throws URISyntaxException, IOException {
        Configuration configuration = new Configuration();
        FileSystem fileSystem = FileSystem.newInstance(new URI("hdfs://mycluster:8020"), configuration);
        return fileSystem;
    }


    //    第四种
    public FileSystem getFileSystem4() throws Exception {
        Configuration configuration = new Configuration();
        configuration.set("fs.defaultFS", "hdfs://mycluster:8020");
        FileSystem fileSystem = FileSystem.newInstance(configuration);
        return fileSystem;
    }
}

二、Hadoop1.0到Hadoop2.0的改进

Hadoop2.0主要添加了HA高可用和Federation联邦机制

在这里插入图片描述

1.HDFS HA

对于分布式文件系统HDFS ,NN是系统的核心节点,存储了各类元数据信息,并负责管理文件系统的命名空间和客户端对文件的访问。但是,在HDFS1.0中,只存在一个NN,一旦发生“单点故障”,就会导致整个系统失效。虽然有个SNN,但是它并不是NN的热备份,SNN主要功能在于周期性的从NN中获取FsImage和EditLog,进行合并后再发送给NN,替换掉原来的FsImage,以防止EditLog文件过大,导致NN失败恢复时消耗太多时间。合并后的FsImage在SNN中也保存一份,当NN失效时,可以利用SNN中的FsImage进行恢复。

由于SNN无法提供“热备份”功能,在NN发生故障时,无法立即切换到SNN对外提供服务,仍需要停机恢复。HDFS2.0采用了HA(High Availability)架构。在HA集群中,一般设置两个NN,其中一个处于“活跃(Active)”状态,另一个处于“待命(Standby)”状态。处于Active状态的NN负责对外处理所有客户端的请求,处于Standby状态的NN作为热备份节点,保存了足够多的元数据,在Active节点发生故障时,立即切换到活跃状态对外提供服务。
在这里插入图片描述
由于Standby NN是Active NN的“热备份”,因此Active NN的状态信息必须实时同步到StandbyNN。针对状态同步,可以借助一个共享存储系统来实现,如NFS(NetworkFile System)、QJM(Quorum Journal Manager)或者Zookeeper。Active NN将更新数据写入到共享存储系统,Standby NN会一直监听该系统,一旦发现有新的写入,就立即从公共存储系统中读取这些数据并加载到自己内存中,从而保证与Active NN状态一致。

此外,NN保存了数据块到实际存储位置的映射信息,即每个数据块是由哪个DN存储的。当一个DN加入到集群中时,它会把自己所包含的数据块列表给NN,定期通过心跳方式,以确保NN中的块映射是最新的。因此,为了实现故障时的快速切换,必须保证StandbyNN中也包含最新的块映射信息,为此需要给DN配置Active和Standby两个NN的地址,把块的位置和心跳信息同时发送到两个NN上。为了防止出现“两个管家”现象,还要保证在任何时刻都只有一个NN处于Active状态,需要Zookeeper实现。

2.HDFS Federation

在HDFS联邦中,设计了多个相互独立的NameNode,使得HDFS的命名服务能够水平扩展,这些NameNode分别进行各自命名空间和块的管理,不需要彼此协调。每个DataNode要向集群中所有的NameNode注册,并周期性的发送心跳信息和block块信息,报告自己的状态。

HDFS联邦机制拥有多个独立的命名空间,其中,每一个命名空间管理属于自己的一组块,这些属于同一个命名空间的块组成一个“块池”。每个DataNode会为多个块池提供块的存储,块池中的各个块实际上是存储在不同DataNode中的。
在这里插入图片描述

  • 15
    点赞
  • 23
    收藏
    觉得还不错? 一键收藏
  • 5
    评论
评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值