从零学习HDFS—Hadoop生态圈(一)

HDFS介绍

        HDFS (Hadoop Distributed File System)是 Hadoop 下的分布式文件系统,具有高容错、高吞吐量等特性,可以部署在低成本的硬件上。


HDFS设计假设和目标

  • 硬件故障:HDFS实例可能包含数百或数千个服务器计算机;存在大量组件并且每个组件都有不小的故障概率这一事实意味着HDFS的某些组件始终无法正常工作;**检测故障并从故障中快速自动恢复是HDFS的核心架构目标;
  • 流数据访问:在HDFS上运行的应用程序需要对其数据集的流访问。HDFS设计用于批处理,而不是用户交互使用。重点在于数据访问的高吞吐量,而不是数据访问的低延迟;
  • 大数据集:在HDFS上运行的应用程序具有大量数据集。HDFS中的典型文件大小为GB到TB;
  • 简单一致性模型:HDFS应用程序需要文件一次写入多次读取访问模型。。一旦创建,写入和关闭文件,除了追加和截断外,无需更改。支持将内容追加到文件末尾,但不能在任意点更新。该假设简化了数据一致性问题并实现了高吞吐量数据访问。
  • “移动计算比移动数据便宜”:如果应用程序所请求的计算在其所操作的数据附近执行,则效率会更高。假设通常是将计算迁移到更靠近数据的位置,而不是将数据移动到应用程序正在运行的位置。
  • 跨异构硬件和软件平台的可移植性:HDFS被设计为可从一个平台轻松移植到另一个平台。这有助于将HDFS广泛用作大量应用程序的首选平台;

HDFS设计原理

官网原图

1.HDFS组成

        架构主要由以下四部分组成:

  • HDFS Client::客户端
(1)文件切分。文件上传 HDFS的时候, Client将文件切分成一个一个的 Block,然后进行存储;
(2)与 NameNode 交互,获取文件的位置信息;
(3)与 DataNode 交互,读取或者写入数据;
(4)Client 提供一些命令来管理 HDFS ,eg:start-all.sh;
(5)Client 可以通过一些命令来访问 HDFS;

  • NameNode:元数据节点
(1)管理 HDFS的名称空间(文件目录树);
(2)管理Block映射信息及副本信息;
(3)处理客户端读写请求;

  • DateNode:实际数据存储节点
(1)存储实际的数据块;
(2)执行数据块的读 /写操作;

  • SecondaryNameNode:并非 NameNode的热备。当 NameNode挂掉的时候,它并不能马上替换 NameNode并提供服务;
(1)辅助 NameNode,分担其工作量;
(2)定期合并 Fsimage和 Edits,并推送给 NameNode;
(3)在紧急情况下,可辅助恢复 NameNode;

2.block(文件块)大小

        Hadoop物理存储数据是以block存储的,存储的位置在本地磁盘{hadoop.tmp.dir}/dfs/data,块的大小可以通过配置参数( dfs.blocksize)来规定,默认大小在 Hadoop2.x版本中是128M Hadoop1.x版本中是64M。
        HDFS的块比磁盘块大,目的是为了最小化寻址开销。如果块设置的足够大,从磁盘传输数据的时间可以明显大于定位这个块开始位置所需要的时间。这样,传输一个由多个块组成的文件的时间取决于磁盘传输速率。
        寻址时间10ms左右,HDFS使让块寻址时间占用读取时间的1%,以传输速率100MB/s为例,设置块大小为128MB。但是该参数也不会设置得过大。MapReduce中的map任务通常一次处理一个块中的数据,因此如果任务数太少(少于集群中的节点数量),作业的运行速度就会比较慢。

在这里插入图片描述


  • 副本机制
    在这里插入图片描述
        副本作用:避免数据丢失
        存放机制:三分之一的副本位于一个节点上,三分之二的副本位于一个机架上,其余三分之一则平均分布在其余机架上。此策略可提高写入性能,而不会影响数据可靠性或读取性能。

3.HDFS优缺点

HDFS优点:

  • 高容错性:数据副本多,并可提高副本个数,从而提高容错性;某个副本丢失后,可以自动恢复
  • 适合大数据处理:能处理GB、甚至TB级别的数据;文件数量达上百万规模;
  • 流式数据访问:一次写入多次读取,文件写入后不能修改,只能追加;保证数据的一致性;
  • 搭建成本低:可构建在廉价机器上;

HDFS缺点:

  • 不适合低延时数据访问,比如毫秒级的存储数据,是做不到的;
  • 无法高效的对大量小文件进行存储;小文件过多的话,它会占用 NameNode大量的内存来 存储文件的目录和块信息;小文件存储的寻址时间会超过读取时间,它违反了HDFS的设计目标。
  • 不支持并发写入、文件随机修改;

HDFS的Shell命令

HDFS有三种shell命令方式:

  • hadoop fs :适用于任何不同的文件系统,比如本地文件系统和HDFS文件系统。
  • Hadoop dfs:只能适用与HDFS文件系统。
  • hdfs dfs:跟hadoop dfs命令作用一样,也只能适用与HDfS文件系统。

以下是一些对文件和文件夹操作的shell命令:

hdfs dfs -mkdir input
#在HDFS文件系统中创建一个'input'目录

hdfs dfs -ls input
#列出 input 目录下的内容

hdfs dfs -put /home/hadoop/myFlie.txt input
#将本地的文件myFile.txt上传到HDFS文件系统的input中。

hdfs dfs -get input/myFlie.txt /home/hadoop/下载
#从HDFS文件系统中下载文件到本地文件系统

hdfs dfs -cat input/myFlie.txt
#查看文件的全部内容

hdfs dfs -cp input/myFile.txt input
#在HDFS上复制文件

hdfs dfs -mv input/myFile.txt output
#在HDFS上移动文件

hdfs dfs -rm input/myFile.txt 
#从HDFS删除文件

hdfs dfs -du input/myFile.txt
#查看HDFS上某目录下所有文件大小,指定文件后显示具体文件大小

hdfs dfs -touchz input/file.txt
#创建一个0字节的空文件。

hdfs dfs -chmod 
#改名文件权限

hdfs dfs -chown 
#改变文件所有者


Java操作HDFS

参考博客:java操作Hdfs


HDFS读写流程

1.写数据

在这里插入图片描述

  • 创建文件:

    • HDFS客户端向HDFS写数据,先调用DistributedFileSystem.create()方法,在HDFS创建新的空文件;

    • RPC(ClientProtocol.create())远程过程调用NameNode(NameNodeRpcServer)的create(),首先在HDFS目录树指定路径添加新文件;

    • 然后将创建新文件的操作记录在editslog中;

    • NameNode.create方法执行完后,DistributedFileSystem.create()返回FSDataOutputStream,它本质是封装了一个DFSOutputStream对象;

  • 建立数据流管道:

    • 客户端调用DFSOutputStream.write()写数据;

    • DFSOutputStream调用ClientProtocol.addBlock(),首先向NameNode申请一个空的数据块;

    • addBlock()返回LocatedBlock对象,对象包含当前数据块的所有datanode的位置信息;

    • 根据位置信息,建立数据流管道;

  • 向数据流管道pipeline中写当前块的数据:

    • 客户端向流管道中写数据,先将数据写入一个检验块chunk中,大小512Byte,写满后,计算chunk的检验和checksum值(4Byte);

    • 然后将chunk数据本身加上checksum,形成一个带checksum值的chunk(516Byte);

    • 保存到一个更大一些的结构packet数据包中,packet为64kB大小;

  • packet写满后,先被写入一个dataQueue队列中

    • packet被从队列中取出,向pipeline中写入,先写入datanode1,再从datanoe1传到datanode2,再从datanode2传到datanode3中;
  • 一个packet数据取完后,后被放入到ackQueue中等待pipeline关于该packet的ack的反馈;

    • 每个packet都会有ack确认包,逆pipeline(dn3 -> dn2 -> dn1)传回输出流;
  • 若packet的ack是SUCCESS成功的,则从ackQueue中,将packet删除;否则,将packet从ackQueue中取出,重新放入dataQueue,重新发送

    • 如果当前块写完后,文件还有其它块要写,那么再调用addBlock方法(流程同上);
  • 文件最后一个block块数据写完后,会再发送一个空的packet,表示当前block写完了,然后关闭pipeline;

    • 所有块写完,close()关闭流;
  • ClientProtocol.complete()通知namenode当前文件所有块写完了;


容错:

在写的过程中,pipeline中的datanode出现故障(如网络不通),输出流如何恢复

  • 输出流中ackQueue缓存的所有packet会被重新加入dataQueue;

  • 输出流调用ClientProtocol.updateBlockForPipeline(),为block申请一个新的时间戳,namenode会记录新时间戳;

  • 确保故障datanode即使恢复,但由于其上的block时间戳与namenode记录的新的时间戳不一致,故障datanode上的block进而被删除;

  • 故障的datanode从pipeline中删除;

  • 输出流调用ClientProtocol.getAdditionalDatanode()通知namenode分配新的datanode到数据流pipeline中,并使用新的时间戳建立pipeline;

  • 新添加到pipeline中的datanode,目前还没有存储这个新的block,HDFS客户端通过DataTransferProtocol通知pipeline中的一个datanode复制这个block到新的datanode中;

  • pipeline重建后,输出流调用ClientProtocol.updatePipeline(),更新namenode中的元数据;

  • 故障恢复完毕,完成后续的写入流程;


2.读数据

在这里插入图片描述
详细流程:

  • 1、client端读取HDFS文件,client调用文件系统对象DistributedFileSystem的open方法;

  • 2、返回FSDataInputStream对象(对DFSInputStream的包装);

  • 3、构造DFSInputStream对象时,调用namenode的getBlockLocations方法,获得file的开始若干block(如blk1, blk2, blk3, blk4)的存储datanode(以下简称dn)列表;针对每个block的dn列表,会根据网络拓扑做排序,离client近的排在前;

  • 4、调用DFSInputStream的read方法,先读取blk1的数据,与client最近的datanode建立连接,读取数据;

  • 5、读取完后,关闭与dn建立的流;

  • 6、读取下一个block,如blk2的数据(重复步骤4、5、6);

  • 7、这一批block读取完后,再读取下一批block的数据(重复3、4、5、6、7);

  • 8、完成文件数据读取后,调用FSDataInputStream的close方法;


容错:
  • 情况一:读取block过程中,client与datanode通信中断

    • client与存储此block的第二个datandoe建立连接,读取数据

    • 记录此有问题的datanode,不会再从它上读取数据

  • 情况二:client读取block,发现block数据有问题

    • client读取block数据时,同时会读取到block的校验和,若client针对读取过来的block数据,计算检验和,其值与读取过来的校验和不一样,说明block数据损坏

    • client从存储此block副本的其它datanode上读取block数据(也会计算校验和)

    • 同时,client会告知namenode此情况


NN与SNN工作机制

  • NameNode启动
    • 第一次启动NameNode格式化后,创建fsimage和edits文件。如果不是第一次启动,直接加载编辑日志和镜像文件到内存;
      • fsimage::HDFS文件系统元数据的一个永久性的检查点,其中包含HDFS文件系统的所有目录和文件idnode的序列化信息;
      • Edits文件:存放HDFS文件系统的所有更新操作的路径,文件系统客户端执行的所有写操作首先会被记录到edits文件中;
    • 客户端对元数据进行增删改的请求;
    • NameNode记录操作日志,更新滚动日志;
    • NameNode在内存中对数据进行增删改查。
  • SNN(Secondary NameNode)工作
    • Secondary NameNode询问NameNode是否需要checkpoint。直接带回NameNode是否检查结果;
    • Secondary NameNode请求执行checkpoint;
    • NameNode滚动正在写的edits日志;
    • 将滚动前的编辑日志和镜像文件拷贝到Secondary NameNode;
    • Secondary NameNode加载编辑日志和镜像文件到内存,并合并;
    • 生成新的镜像文件fsimage.chkpoint;
    • 拷贝fsimage.chkpoint到NameNode;
    • NameNode将fsimage.chkpoint重新命名成fsimage;

DateNode工作机制

  • 一个数据块在DataNode上以文件形式存储在对应服务器的磁盘上,包括两个文件,一个是数据本身,一个是元数据包括数据块的长度,块数据的校验和,以及时间戳。
  • DataNode启动后向NameNode注册,通过后,周期性(1小时)的向NameNode上报所有的块信息。
  • 心跳是每3秒一次,心跳返回结果带有NameNode给该DataNode的命令如复制块数据到另一台机器,或删除某个数据块。如果超过10分钟没有收到某个DataNode的心跳,则认为该节点不可用。
  • 集群运行中可以安全加入和退出一些机器。

PS:如果有写错或者写的不好的地方,欢迎各位大佬在评论区留下宝贵的意见或者建议,敬上!如果这篇博客对您有帮助,希望您可以顺手帮我点个赞!不胜感谢!

原创作者:wsjslient

作者主页:https://blog.csdn.net/wsjslient

参考来源:hadoop-hdfs/HdfsDesign.html

参考来源:https://blog.csdn.net/qq_24693837/article/details/103742908


  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值