前端同时传文件和对象_HDFS写文件流程(详细必看)

5f670e23204f235bd19a3815ab8001c1.png

HDFS(Hadoop Distributed File System)是GFS的开源实现。特点如下:

能够运行在廉价机器上,硬件出错常态,需要具备高容错性

流式数据访问,而不是随机读写

面向大规模数据集,能够进行批处理、能够横向扩展

简单一致性模型,假定文件是一次写入、多次读取

缺点:

不支持低延迟数据访问

不适合大量小文件存储(因为每条元数据占用空间是一定的)

不支持并发写入,一个文件只能有一个写入者

不支持文件随机修改,仅支持追加写入

HDFS中的block、packet、chunk,很多博文介绍HDFS读写流程上来就直接从文件分块开始,其实,要把读写过程细节搞明白前,你必须知道block、packet与chunk。下面分别讲述。

block

这个大家应该知道,文件上传前需要分块,这个块就是block,一般为128MB,当然你可以去改,不顾不推荐。因为块太小:寻址时间占比过高。块太大:Map任务数太少,作业执行速度变慢。它是最大的一个单位。

packet

packet是第二大的单位,它是client端向DataNode,或DataNode的PipLine之间传数据的基本单位,默认64KB。

chunk

chunk是最小的单位,它是client向DataNode,或DataNode的PipLine之间进行数据校验的基本单位,默认512Byte,因为用作校验,故每个chunk需要带有4Byte的校验位。所以实际每个chunk写入packet的大小为516Byte。由此可见真实数据与校验值数据的比值约为128 : 1。(即64*1024 / 512)

例如,在client端向DataNode传数据的时候,HDFSOutputStream会有一个chunk buff,写满一个chunk后,会计算校验和并写入当前的chunk。之后再把带有校验和的chunk写入packet,当一个packet写满后,packet会进入dataQueue队列,其他的DataNode就是从这个dataQueue获取client端上传的数据并存储的。同时一个DataNode成功存储一个packet后之后会返回一个ack packet,放入ack Queue中。

(一)Java力度去分析写文件流程

1.调用客户端的对象DistributedFileSystem的create方法;

2.DistributedFileSystem会发起对namenode的一个RPC连接,请求创建一个文件,不包含关于block块的请求。namenode会执行各种各样的检查,确保要创建的文件不存在,并且客户端有创建文件的权限。如果检查通过,namenode会创建一个文件(在edits中),否则创建失败,客户端抛异常IOException。

3.DistributedFileSystem返回一个FSDataOutputStream对象给客户端用于写数据。FSDataOutputStream封装了一个DFSOutputStream对象负责客户端跟datanode以及namenode的通信。

4.FSDataOutputStream对象将数据切分为小的数据包(64kb),并写入到一个内部队列(“数据队列”)。DataStreamer会读取其中内容,并请求namenode返回一个datanode列表来存储当前block副本。列表中的datanode会形成管线,DataStreamer将数据包发送给管线中的第一个datanode,第一个datanode将接收到的数据发送给第二个datanode,第二个发送给第三个。。。

5.DFSOoutputStream维护着一个数据包的队列,这的数据包是需要写入到datanode中的,该队列称为确认队列。当一个数据包在管线中所有datanode中写入完成,就从ack队列中移除该数据包。队列是在客户端维护的。

6.如果在数据写入期间datanode发生故障,则执行以下操作

a、关闭管线,把确认队列中的所有包都添加回数据队列的最前端,以保证故障节点下游的datanode不会漏掉任何一个数据包。

b、为存储在另一正常datanode的当前数据块指定一个新的标志,并将该标志传送给namenode,以便故障datanode在恢复后可以删除存储的部分数据块。

c、如果在数据写入期间datanode发生故障,待确认消息队列迟迟得不到确认消息,这时会有一个超时时间,超过这个时间,从管线中删除故障数据节点并且把余下的数据块写入管线中另外两个正常的datanode(也就是这两个节点组成新的管线并且blockID的值要发生变化,另外注意正常的节点中包括之前上传的部分小的64K文件,所以需要对其就行一个统计,确认我现在数到第几个包了,避免重复提交)。namenode在检测到副本数量不足时,会在另一个节点上创建新的副本。

d、后续的数据块继续正常接受处理。

7.在一个块被写入期间可能会有多个datanode同时发生故障,但非常少见。只要设置了dfs.replication.min的副本数(默认为1),写操作就会成功,并且这个块可以在集群中异步复制,直到达到其目标副本数(dfs.replication默认值为3)。

8.如果有多个block,则会反复从步骤4开始执行。

9.当客户端完成了数据的传输,调用数据流的close方法。该方法将数据队列中的剩余数据包写到datanode的管线并等待管线的确认

10.客户端收到管线中所有正常datanode的确认消息后,通知namenode文件写完了。

11.客户端完成数据的写入后,对数据流调用close方法。该操作将剩余的所有数据包写入datanode管线,并在联系到namenode且发送文件写入完成信号之前,等待确认。

namenode已经知道文件由哪些块组成,所以它在返回成功前只需要等待数据块进行最小量的复制。

注意:如果在数据写入期间datanode发生故障,待确认消息队列迟迟得不到确认消息,这时会有一个超时时间,超过这个时间

文件写文件的时候只有一个客户端能写,保证数据上传成功

(二)写文件流程理解二

1.客户端向NameNode发出写文件请求。

2.namenode收到客户端的请求后,首先会检测元数据的目录树;检查权限并判断待上传的文件是否已存在,如果已存在,则拒绝client的上传。如果不存在,则响应客户端可以上传。

(注:WAL,write ahead log,先写Log,再写内存,因为EditLog记录的是最新的HDFS客户端执行所有的写操作。如果后续真实写操作失败了,由于在真实写操作之前,操作就被写入EditLog中了,故EditLog中仍会有记录,我们不用担心后续client读不到相应的数据块,因为在第5步中DataNode收到块后会有一返回确认信息,若没写成功,发送端没收到确认信息,会一直重试,直到成功)

3. 客户端收到可以上传的响应后,会把待上传的文件切块(hadoop2.x默认块大小为128M);然后再次给namenode发送请求,上传第一个block块。

4.namenode收到客户端上传block块的请求后,首先会检测其保存的datanode信息,确定该文件块存储在那些节点上;最后,响应给客户端一组datanode节点信息。

5.客户端根据收到datanode节点信息,首先就近与某台datanode建立网络连接;然后该datanode节点会与剩下的节点建立传输通道,通道连通后返回确认信息给客户端;表示通道已连通,可以传输数据。

6. 客户端收到确认信息后,通过网络向就近的datanode节点写第一个block块的数据;就近的datanode收到数据后,首先会缓存起来;然后将缓存里数据保存一份到本地,一份发送到传输通道;让剩下的datanode做备份。

client将NameNode返回的分配的可写的DataNode列表和Data数据一同发送给最近的第一个DataNode节点,此后client端和NameNode分配的多个DataNode构成pipeline管道,client端向输出流对象中写数据。client每向第一个DataNode写入一个packet,这个packet便会直接在pipeline里传给第二个、第三个…DataNode。

(注:并不是写好一个块或一整个文件后才向后分发)

每个DataNode写完一个块后,会返回确认信息。

(注:并不是每写完一个packet后就返回确认信息,个人觉得因为packet中的每个chunk都携带校验信息,没必要每写一个就汇报一下,这样效率太慢。正确的做法是写完一个block块后,对校验信息进行汇总分析,就能得出是否有块写错的情况发生)

7.第一个block块写入完毕,若客户端还有剩余的block未上传;则客户端会从(3)开始,继续执行上述步骤;直到整个文件上传完毕。

写完数据,关闭输输出流。

发送完成信号给NameNode。

(注:发送完成信号的时机取决于集群是强一致性还是最终一致性,强一致性则需要所有DataNode写完后才向NameNode汇报。最终一致性则其中任意一个DataNode写完后就能单独向NameNode汇报,HDFS一般情况下都是强调强一致性)

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值