Hadoop-分布式系统HDFS学习


  • 分布式文件系统(Distributed File System)是一种通过网络实现文件在多台主机上进行分布式存储的文件系统。一般采用客户服务器方式,客户端以特定的通信协议通过网络与服务器建立连接,提出文件访问请求。客户端和服务器可以通过设置访问权限来限制请求方对底层数据存储块的访问。
  • NameNode负责文件和目录的创建、删除和重命名等(元数据),同时管理着DataNode和文件块的映射关系,因此客户端只有访问NameNode才能找到请求的文件块所在的位置,进而到相应位置读取所需文件块。在整个访问过程,NameNode不参与实际数据的传输。
    DataNode负责数据的存储和读取,其要根据NameNode的命令创建、删除数据库和冗余复制。
  • 存储时,由NameNode分配存储位置,然后由客户端把数据直接写入相应的DataNode。
    读取时,客户端从NameNode获得DataNode和文件块的映射关系,然后就可以到相应位置访问文件块。

HDFS的局限性

  1. 不适合低延迟数据访问。HDFS主要是面向大规模数据批量处理而设计的,采用流式数据读取,具有很高的数据吞吐率,但也意味着较高的延迟。对于低延时需求的应用程序而言,HBase是一个更好的选择。
  2. 无法高效存储大量小文件。首先,HDFS采用NameNode来管理文件系统的元数据,这些元数据被保存在内存中,从而使客户端可以快速获取文件实际存储位置。通常,每个文件、目录或块占150字节(不管其大小是多少),大量的小文件所需要的内存空间会急剧增加。其次,用MapReduce处理小文件时,会产生过多的Map任务,线程管理开销会大大增加,因此处理大量小文件的速度远远低于处理同等大小的大文件的速度。再次,访问大量小文件的速度远远低于访问同等大小的大文件的速度,因为访问大量小文件需要不断从一个DataNode跳到另一个DataNode,严重影响性能。
  3. 不支持多用户同时写入及任意修改文件。HDFS只允许一个文件在同一时间有一个写入者,不允许多个用户对同一个文件同时进行写操作,而且只允许对文件执行追加操作,不允许执行随机写操作。

HDFS的相关概念

    HDFS的块默认为128M,这么做是为了减少寻址开销。HDFS的寻址开销不仅包括磁盘寻道开销,还包括数据块的定位开销。但块的大小不能太大,通常MapReduce中的Map任务一次只处理一个块的数据,如果启动的任务太少会降低作业并行处理速度。
    使用块的好处

  1. 支持大规模文件存储。一个大规模文件可以拆分成若干个文件块,不同的文件块可以被分到不同的节点,因此一个文件的大小不会受到单个节点的存储容量的限制,文件可以远远大于网络中任意节点的存储容量
  2. 大大简化了存储管理,因为文件块大小是固定的,可以容易计算一个节点可以存储多少个文件块。也方便了元数据的管理,元数据不需要和文件块一起存储,可以由其他系统负责管理元数据。
  3. 适合备份。每个文件块都可以冗余存储到多个节点上,大大提高了系统的容错性和可用性
  4. 一个文件的数据能够在不同的数据节点上并发访问,大大提高了数据访问速度。

NameNode

    NameNode负责管理分布式文件系统的命名空间,其中有两个核心数据结构:FsImageEditLog。FsImage用于维护文件系统树以及文件树中所有的文件和文件夹的元数据。EditLog记录了所有针对文件的创建、删除、重命名等操作。
    NameNode在启动时,会将FsImage内容加载到内存当中,然后执行EditLog文件中的各种操作使得内存中的元数据保持最新。这个操作完成之后,就会创建一个新的FsImage文件和一个空的EditLog文件。NameNode启动成功并进入正常状态以后,HDFS中的更新操作都会写入EditLog,而不是直接写入FsImage。
    NameNnde在启动的过程中处于安全模式,只能对外提供读操作,无法提供写操作。启动过程结束后,系统就会退出安全模式(文件系统99.9%块满足最小副本条件(dfs.replication.min=1)),进入正常运行状态。对外提供读写操作。
    bin/hdfs dfsadmin -safemode get (查看安全模式状态)
    bin/hdfs dfsadmin -safemode enter (进入安全模式状态)
    bin/hdfs dfsadmin -safemode leave (离开安全模式状态)
    bin/hdfs dfsadmin -safemode wait (等待安全模式状态)

NameNode故障处理

    NameNode故障后,可以采用如下两种方法恢复数据。
    方法一:将Secondary NameNode中的数据拷贝到NameNode存储数据的目录;

  1. kill -9 NameNode进程
  2. 删除NameNode存储的数据(/opt/hadoop-2.9.2/data/tmp/dfs/name/*)
  3. 拷贝Secondary NameNode中数据到原NameNode存储数据目录
    scp -r root@slave2:/opt/hadoop-2.9.2/data/tmp/dfs/namesecondary/* ./name/
  4. 重新启动NameNode
    sbin/hadoop-daemon.sh start namenode

    方法二:使用 -importCheckpoint 选项启动NameNode守护进程,从而将Secondary NameNode中数据拷贝到NameNode目录中。

  1. 修改hdfs-site.xml

     <property>
       <name>dfs.namenode.checkpoint.period</name>
       <value>120</value>
     </property>
     
     <property>
       <name>dfs.namenode.name.dir</name>
       <value>/opt/hadoop-2.9.2/data/tmp/dfs/name</value>
     </property>
    
  2. kill -9 NameNode进程

  3. 删除NameNode存储的数据(/opt/hadoop-2.9.2/data/tmp/dfs/name/*)

  4. 如果Secondary NameNode不和NameNode在一个主机节点上,需要将Secondary NameNode存储数据的目录拷贝到NameNode存储数据的平级目录,并删除in_use.lock文件
    scp -r root@slave2:/opt/hadoop-2.9.2/data/tmp/dfs/namesecondary /opt/hadoop-2.9.2/data/tmp/dfs
    rm -rf in_use.lock

  5. 导入检查点数据(等待一会ctrl+c结束掉)
    bin/hdfs namenode -importCheckpoint

  6. 启动NameNode
    sbin/hadoop-daemon.sh start namenode

多目录配置

    NameNode的本地目录可以配置成多个,且每个目录存放内容相同,增加了可靠性。
    在hdfs-site.xml文件中增加如下内容

<property>
    <name>dfs.namenode.name.dir</name>
	<value>file:///${hadoop.tmp.dir}/dfs/name1,file:///${hadoop.tmp.dir}/dfs/name2</value>
</property>

DataNode

    DataNode是分布式文件系统HDFS的工作节点,负责数据的存储和读取,会根据客户端或NameNode调度来进行数据的存储和检索,并且定期向NameNode发送自己所存储的块的列表。每个数据节点中的数据都会被保存到各自节点的本地的Linux文件系统中。每个DataNode会周期性地向NameNode发送“心跳”信息,报告自己的状态,没有按时发送的DataNode会被标记为“宕机”,不在给它分配任务I/O请求。

Secondary NameNode

    在NameNode运行期间,HDFS会不断发生更新操作,这些操作直接被写入到EditlLog文件,因此EditlLog会逐渐变大。当NameNode重启时,需要将FsImage加载到内存,然后执行EditlLog中的记录,使得FsImage保持最新。如果EditlLog很大,就会导致整个过程变得非常缓慢,使得NameNode在启动过程中长期处于安全模式,无法正常对外提供写操作。
    为了解决EditlLog逐渐增大的问题,HDFS在设计上采用Secondary NameNode,完成FsImage和EditlLog的合并操作,减小EditlLog文件大小,缩短NameNode重启时间。同时可以作为NameNode检查点(check point),保存NameNode元数据信息(相当于备份)。

FsImage和EditlLog的合并操作

  1. 每隔一段时间,Secondary NameNode会和NameNode通信(检查时间到,Secondary NameNode发送检查请求 或 EditLog已满,NameNode发送合并请求),然后NameNode停止使用EditlLog(t1时刻),并暂时将新到达的写操作写入一个新的文件EditlLog.new中。
  2. Secondary NameNode把NameNode的FsImage和EditlLog拉回本地,再加载到内存中,对二者执行合并操作,即在内存中逐条执行EditLog中的操作,使得FsImage保持最新。
  3. 合并完成后,Secondary NameNode把最新的FsImage发送到NameNode。
  4. NameNode收到后,会用最新的FsImage替换旧的FsImage,同时用EditlLog.new替换EditlLog(t2时刻),从而缩小EditlLog的大小。
    在这里插入图片描述

CheckPoint设置

  1. Secondary NameNode每隔一小时执行一次合并操作

     [hdfs-default.xml]
     <property>
       <name>dfs.namenode.checkpoint.period</name>
       <value>3600</value>
     </property>
    
  2. 当操作次数达到1百万时,Secondary NameNode执行一次合并操作

     [hdfs-default.xml]
     <property>
       <name>dfs.namenode.checkpoint.txns</name>
       <value>1000000</value>
       <description>操作动作次数</description>
     </property>
    

作为NameNode的检查点

    Secondary NameNode会和NameNode通信,得到FsImage和EditlLog。合并后得到最新的FsImage,相当于周期性备份NameNode的元数据信息。当NameNode发生故障,可以用Secondary NameNode记录的元数据信息进行系统恢复。如果NameNode在t1时刻到t2时刻发生故障,只能备份t1时刻之前的,t1时刻到t2时刻的数据会丢失。

  • HDFS集群中只有唯一一个NameNode和任意多个DataNode,该NameNode节点负责所有元数据的管理。这种设计大大简化的分布式文件系统的结构。可以保证数据不会脱离NameNode的控制。同时,用户数据也永远不会经过NameNode,这大大减轻了中心服务器的负担,方便了数据的管理。

HDFS通信协议

    HDFS是一个部署在集群上的分布式文件系统,因此很多数据需要通过网络进行传输,所有的HDFS通信协议都是建立在TCP/IP协议基础之上。客户端通过一个可配置的端口向NameNode主动发起TCP连接,并使用客户端协议与NameNode进行交互。NameNode和DataNode之间则使用数据节点协议进行交互,客户端与DataNode的交互是通过RPC(Remote Procedure Call)来实现的。在设计上,NameNode不会主动发起RPC,而是响应来自客户端和DataNode的请求

HDFS体系结构的局限性

  1. 命名空间的限制:NameNode是保存在内存中的,因此NameNode能够容纳对象(文件、块)的个数会受到内存空间大小的限制。
  2. 性能的瓶颈,整个分布式系统的吞吐量受限于单个NameNode的吞吐量。
  3. 隔离问题:由于集群中只有一个NameNode,因此无法对不同应用程序进行隔离。
  4. 集群的可用性:一旦这个唯一的NameNode发生故障,会导致整个集群变得不可用。

HDFS的存储原理

  • 为了保证系统的容错性和可用性,HDFS采用多副本方式对数据进行冗余存储,通常一个数据块的多个副本会被分布在不同的DataNode。这样做的优点是:
    1. 加快数据传输速度。当多个客户需要同时访问同一个文件时,可以让各个客户端分别从不同的数据块副本中读取数据,大大加快了数据传输速度。
    2. 容易检测数据错误
    3. 保证数据的可靠性。即使某个DataNode出现故障失效,也不会造成数据丢失。
      在这里插入图片描述

Rack Awareness

  • HDFS采用以机架(Rack)为基础的数据存放策略。一个HDFS集群通常包含多个机架,不同机架之间的数据通信需要经过交换机或者路由器,同一个机架的不同机器之间的通信不需要经过交换机或者路由器。所以,同一个机架中不同机器之间的通信比不同机架之间机器的通信带宽大
        Rack Awareness:根据机架的信息选取最近的DataNode。
  • Rack Awareness策略
    1. 同一个节点存放不超过一个副本
    2. 同一个机架存放不超过两个副本
    3. 存放副本的机架数量应该一直小于副本数

    HDFS的默认冗余复制因子为3(副本数)。每个文件块会被同时保存到3个地方,其中有两份副本在同一个机架的不同节点上,第三个副本放在不同机架的节点上,既保证了机架方式异常时的数据恢复,提高容错性和可用性,也提高了数据的读写性能,减少读写延迟。

流水线复制

  • HDFS的数据复制采用流水线复制策略。
    1. 当客户端要往HDFS中写入一个文件时,这个文件会首先被写入客户端本地,并被分割成若干个块。
    2. 每个块都向HDFS集群中的NameNode发起写请求,NameNode会根据系统中各个DataNode的使用情况,选择一个DataNode列表返回给客户端。
    3. 客户端把数据首先写入列表中的第一个DataNode,同时把列表传给第一个DataNode。
    4. 当第一个DataNode接收到4KB数据的时候,写入本地,并向列表中第二个DataNode发起连接请求,把自己已经收到的4KB数据和列表传给第二个DataNode。
    5. 当第二个DataNode接收到4KB数据的时候,写入本地,并且向列表中的第三个DataNode发起连接请求,以此类推。

HDFS的数据读写过程

Hadoop-HDFS的数据读写过程(详细过程与图解)

HDFS的可扩展性

垂直扩展(Vertical Scaling)

    我们可以向集群中的节点加更多的硬盘,我们需要修改配置文件以及对新加入的硬盘做一些操作。这个过程需要一个停机时间(downtime),所以实际开发中更偏向于水平扩展。

水平扩展(Horizontal Scaling)

    我们可以在集群正常运行的时候向集群添加更多的节点,这个过程不需要停机时间,我们可以实时添加。

猜你喜欢

转载自blog.csdn.net/H_X_P_/article/details/105908661