HDFS的读写流程
HDFS的读写流程
写数据
1、宏观
1、客户端发起请求到NameNode,调用Hadoop中的一个类叫做DistributedFileSystem创建对象,再利用这个对象通过RPC通信协议调用NameNode去创建一个没有blocks关联的新文件。在创建之前NameNode会做各种校验:比如该文件是否存在,客户端有无权限去创建...如果校验通过,NameNode就会记录下新文件,否则传出IO异常。
2、 如果校验成功,那就会返回给客户端一个FSDataOutoutStream对象(相当于输出流),客户端可以利用这个对象去写数据。客户端开始对文件进行切分,切分成一个个block块。
3、客户端写数据之前要想NameNode询问这个新些block最适合存储的在哪几个datanode里,要向那个节点上写入数据。假设所创建的文件叫a.txt,在NameNode校验成功后,会进行一系列分析生成a.txt的文件信息(副本信息与存放节点的信息)。而且在NameNode分析计算出来哪几个节点适合去存储这个新文件及其副本,在这几个节点之间会生成一个通道pipeline.DataStreamer【pipeline.DataStreamer是通过数据流来处理的,DataStreamer是Hadoop中的一个类,用于接受数据队列data queue】
4、客户端从NameNode得到信息后会将数据打包成一个个packet,一个block块中有2048个packet,一个packet的大小为64kb。客户端会通过机架感知获取最近的子节点建立连接通道。客户端利用NameNode的FSDataOutoutStream将packet发送到第一个子节点上。然后在第一个子节点中,然后根据副本信息将packet通过各个子节点之间的pipeline通道发送到各个子节点上去(由NameNode分析计算得出的节点),当发送到最后一个子节点时,子节点会方向沿着pipeline通道发送一个ack值一直到第一个子节点,最后将这个ack值发送给客户端,客户端以ack值来判断来各个节点已经收到了第一个packet。由此客户端开始已同样的方法发送第二个packet,以此类推。
5、当文件中最后一个block块中 最后一个package返回的ack值到达客户端,客户端关FSDataOutoutStream流,子节点之间的pipeline通道断开,HDFS写数据完毕
宏观写数据角度引出的思考:
package在传输过程中,若突然断电或其他异常导致传输中断,有可能会导致数据丢失
客户端怎么知道当前的ack确认值表示的是最后一个package
2、微观
1、当客户端要上传一个文件时,要先将文件切分为一个个block块,一个block块又分为一个个packet。然后通过FSDataOutoutStream将一个个packet发送到最近的子节点上。
2、一个package由两大部分构成,packet header和packet data。package hearder中有有pkt Len,offset In Pkt,SeqNo,Last Packet In Block,Data Len。Last Packet In Block就是存储是不是最后一个packet的信息true或者false。packetdata又分为ChunkData和Chunk Check sum,每个Check sum是负责校验每个Data是否完整的。
3、当拿到第一个packet时,将packet放入数据队列data queue中,后续的packet依次放入队列中,除了数据队列还有一个确认队列ack queue,当packet要通过FSDataOutoutStream传输给各个子节点之前,客户端会在数据队列中拷贝一份给确认队列然后再发送给第一个子节点,第一个子节点再根据副本信息拷贝给第二个子节点,第二个再拷贝给第三个,节点之间是通过pipeline通道进行数据传输,当packet到达最后一个子节点时,最后一个子节点再拷贝一份packet命名为ack值反向沿着pipeline通道传输给客户端。实际上是传输到客户端中的确认队列,当确认队列收到ackt值时将原本的拷贝的packet删除,至此第一个packet传输完毕。
4、当packet在传输过程中发生异常无法正常传输时,客户端中的确认队列没有收到ack值,然后客户端就会认为在传输过程中出现了异常,然后各个节点删除该packet最后再重新传输。