HDFS的读写流程

hdfs写数据流程
 通过以下代码进入写数据流程:

		FSDataOutputStream fsous=fileSystem.create(new Path("/user.txt"));
		fsous.write("fdsafdsafdsafs".getBytes());

HDFS的读写流程_第1张图片
 由create方法进入客户端代码,通过DistributedFileSystem获取到DFSClient对象最终在DFSOutputStream类中通过NameNodeRpcServer的代理对象远程调用NameNodeRpcServer的create方法创建文件,同时这里还会启动一个非常重要的线程DataStreamer。NameNode通过FSNamesystem创建文件后修改内存中元数据信息并将操作日志写入磁盘,具体流程可见NameNode元数据管理。同时在创建文件后会为这个文件创建一个文件契约(lease)并返回给客户端,用于控制多个客户端写同一个文件,创建契约后NameNode会启动一个后台线程用于监控契约状态,当契约超过1小时没有续约后会在保存契约的sortMap中将之移除,这里用sortMap来保存契约主要是可以排序,树型结构,最早续约的排在最上面的节点,这样这个后台线程只需判断这个最早续约的契约是否超过一小时没有续约就行。客户端拿到契约后也会启动一个后台线程用于续约,并且每隔1秒检查一次契约状态,当超过30秒没有续约后会主动通过rpc向NameNodeRpcServer发起续约请求,NameNode获得请求后会将sortMap中对应的契约的上次续约时间进行更新。至此create的流程基本走完。
 write写入数据,在客户单最终会调用到FSOutputSummer的write方法,这里开始将数据写成一个个的Chunk,一个chunk512个字节+4个字节的校验信息,一个packet默认64K由127个chunk组成。当一个packet写满或者一个block块(默认128M)写满时,会将packet放入dataQueue队列,同时之前启动的DataStreamer线程因为dataQueue没有数据一直在等待,此刻会被唤醒,具体后续代码流程在该线程中。
DataStreamer的工作
 1、DataStreamer此时会通过rpc想NameNode请求block块,NameNode会根据请求及配置的副本数和负载均衡策略为合理的机器创建对应的block信息,并将这些block块信息添加到之前创建的INodeFile上,同时返回给DataStreamer。
 2、这时DataStreamer会根据block信息建立数据管道,会向第一个DataNode发送socket请求建立连接,通过DataNode启动时启动的线程DataXceiverServer来连接(具体流程见DataNode的启动流程和心跳),后续的连接由相应的DataNode依次通过socket以同样的方式建立连接形成管道,并且在发送socket连接时会有三次重试机会,都失败则会放弃这个DataNode重新申请block,申请新的block时会将连接不上的block信息返回给NameNode避免再次被分配到连接不上的那台DataNode。
 3、启动ResponseProcessor线程,用于接收下游DataNode返回的ack信息,若结果是写入成功,则将ackQueue队列中对应的packet移除,然后发送唤醒DataStreamer下一个packet,若结果是写入失败,则会将ackQueu中对应的packet重新写入dataQueue中,继续发送实现容错。
 4、发送数据前会将dataQueue对应的packet移除,添加到ackQueue中,一方面是为了第3点的容错,一方面是给dataQueue腾出空间。
 5、正式发送数据,通过流对拷的形式将数据一个packet一个packet发送给下游的DataNode。

 数据到达第一个DataNode这里时,通过DataXceiverServer线程开启DataXceiver线程,一个DataXceiver线程对应一个block块,根据请求类型来执行后续代码,这里我们是写对应的是WRITE_BLOCK,然后会创建一个关键的线程BlockReceiver,BlockReceiver线程主要有三个作用:

  1. 通过socket连接下游DataNode。
  2. 启动PacketResponder线程用于监听下游返回的ack结果信息,作用类似于客户端中启动的ResponseProcessor线程。结果成功则移除ackQueue中的packet,失败则将ackQueue中的packet继续发送下游。
  3. 接收上游发送过来的packet数据,接收到数据时首先将packet写入ackQueue队列中,然后将这个packet发送给下游节点,最后根据之前客户端将数据写成chunk时的校验信息进行数据的校验,校验通过将数据写入到磁盘。
     数据再管道流通时,若写入失败有ackQueue进行容错,若DataNode宕机或者因为其他原因socket连接不上,在三次重试完后会将失效的DataNode移除管道列表继续发送数据,写数据不要保证所有副本都写入成功,只需要管道中的DataNode写入成功就像,最低一个,后续NameNode会自动平衡副本数。

你可能感兴趣的:(HDFS,hadoop,大数据,hdfs)