文件的写流程
首先客户端和namenode进行建立连接,无论是查询还是创建,都是先进行与namenode进行交互获取元数据,当我们开始提交写请求时,首先客户端会检查文件名、路径是否合法,文件名是否被占用,一系列的检查通过之后那么,会创建一个.copying的一个扩展名的文件,此时namenode触发了块的副本放置策略,因为只有namenode才知道集群的节点信息,机架信息,怎么去放置的信息,触发这个策略是在拿到完整的数据节点清单列表之前进行触发的。 如果客户端在提交请求时在datanode节点上进行提交的,那么潜台词就是说第一的数据块会放到这个datanode上,第二个数据块就会放到出机架的任意一台磁盘不太满、cpu不太忙的节点上,第三个数据块放在与第二个同机架的不同节点上。这里的潜台词有一个距离的概念,如果有其他的应用使用HDFS作为存储层的时候,那些上层应用向hdfs写数据时约等于向本机写,比如说hbase,hbase就是向内存写,但是当内存达到一定的阈值时,会flush到存储层中,又因为存储层是基于hdfs的,而hdfs是默认将第一份数据放到本机上的,而hbase将region的信息写到hdfs,实际上就是写在本机上的。
之后客户端和第一个datanode建立pipeline管道,第一个会连接第二个,第二个连接第三个,并不是客户端连接所有的datanode,当pipeline组件好了之后,客户端在传输这些块的时候,是将这些块切割成更小的package(默认64k),而这里的传输机制就是,客户端通过pipeline将第一个数据包向第一个节点传输,然后第一个会将数据包又传输到第二个节点,第一个节点传输的时候,客户端并不是阻塞的,客户端会一直向第一个传输,就像流水线上的工人一样,第一个工人将工件组装组装完毕扔给第二个,第一个工人不会等待第二个是否忙闲,都会传送给第二个。而在大数据中这种“流水线”式的就是一种变种的并行计算模式,第一个和第二个不是阻塞的。--这点达到了速度快。
队列的概念:
一个是发送的队列,另外一种是确认的队列,
使用队列一般是使用异步的传输方式,而且使用两队列一般是使用两队列。采用的是异步的方式,进行传输的。
当一个数据包在传输的过程中,出现问题的时候,如果一台datanode节点挂掉了那么,在传输过程中,会采用跳过机制,跳过当前故障的节点,对下一个节点进行传输。如果最后一个挂了,那么只传第一个和第二个,如果中间的datanode节点挂了,那么第一个和第三个进行建立连接,继续传递数据,如果第一个挂了,那么客户端和第二个和第三个建立连接,进行传递数据,进行着时间线重叠的概念,这里的有多少个副本而杜宇客户端是透明的了。
当节点挂了,没有达到副本放置策略,由于datanode和namenode之时刻保持着心跳,那么当namenode发现有节点挂掉了,那么会分配一个新的节点去存放数据集,而且会会检查哪些节点上数据块没有达到副本放置策略,那么会将没有达到的数据,进行数据复制一份储存到节点上达到数据的副本策略。
文件的读流程
1.首先客户端和写流程一样先进行文件的格式检查,然后与namenode建立连接,获取所需要的资源的元数据。
2.然后和datanode进行建立连接,然后datanode将客户端所需要的数据发送回去。
刚才这个读流程,我们的语义是将一个完整的数据文件下载回客户端,那么如果它是一个全集操作,那么它的子集就是,能够读取其中某一部分的块,某一个块的细信息,这里我们能够读取一个全集的数据,那么间接地我们也能读取各个子集诶的操作。而存储层上层是计算层,而计算层是基于存储层的,在mr中一个map不是将整个数据块下载下来,而是只下载自己需要的部分数据。一个map对应的一部分数据。
总体来说就是从客户端和namenode建立连接,触发副本放置策略,获取到数据的列表清单,和datanode建立连接,利用一个输入流open打开指定位置的数据,而当开通了一个文件的IO时,会调用seek方法,进行定位到1048576(比如)个字节开始读取数据,跳过了1048576个字节,进行读取数据。