1. Client 向 NameNode 发起读请求;
  2. NameNode 将请求文件的元信息返回给 Client;
  3. Client 根据元信息去对应的 datanode 上取 block,并以追加的方式写文件,完成 block 的拼接工作;
  4. 最后组成完整的文件;

读取 block 并不是一整块拿下来,读取文件都是以二进制流的方式,所以会先创建文件,再将数据内容追加写入文件。

  1. 客户端发起写文件请求,会带上元数据信息;
  2. NameNode 接受到请求后,会做一些校验工作,如文件是否存在、客户端是否有写权限等,并将写操作记录到 edits 文件中,如果写失败,比如断电了,edits 文件中还记录了上一次操作的信息,能够复原上一次操作;
  3. NameNode 将返回每个 block 存放的 DataNode 列表;
  4. 客户端从 block 所属的 DataNode 列表中,假设备份 3 份,根据就近原则开始写操作,比如选择 DataNode1,在写的同时,DataNode1 会将文件信息传递给 DataNode2,DataNode2 接收到后再传递给 DataNode3,DataNode 接收到信息后,再依次返回确认信息,就像流水线一样,1 -> 2 -> 3,这个过程叫 Replication Pipelining。(这里并不涉及真正的写数据)
  5. DataNode 写完之后,会将结果返回给客户端,收到一个成功的结果,客户端就认为写操作已经完成了,剩余两个备份会异步进行。假设 2 -> 3 的过程中写失败了, 3 号机器宕机,2 号收不到成功确认 ack,则会告知 NameNode,NameNode 再重新指定一个 DataNode 进行写操作,1、2 随机选择一个作为写操作的发起端,保证最后是 3 份备份。

使用 Pipeline 的方式进行写操作,不需要客户端写三份备份,因为客户端写文件时是通过网络传输,所有备份由客户端写的话将严重影响写操作的速度。