1. 读流程
- 客户端首先带着读取路径向NameNode发送读取请求
- NameNode接收到请求后,会先判断是否有权限,读取文件是否存在等等,如果都无误则将 文件所在的DataNode的节点位置,发送给客户端部分或者全部的DataNode的节点位置
- 客户端得到文件块存储的位置后,会调用read()方法,去读取数据
- 在读取之前会先进行一个checksum的操作,去判断一下校验和是否正确,正确则读,不正确 则去下一个存放该block块的DataNode节点上读取
- 读取完NameNode这次发送过来的所有的block块后,会再去询问是否还有block块,如果有则接着读取,如果没有则调用close方法,将读取到的文件合并成一个大文件
故障处理 - 读数据的时候,如果DFSInputStream在与DataNode通信时遇到了错误,就会试图从这个块的另外一个最邻近DataNode读取数据,它也会记住那个故障的DataNode,保证以后不会反复读取该节点上后续的块。DFSInputStream也会通过校验和确认从DataNode发来的数据是否完整,如果返现有损坏的块,DFSInputStream会试图从其他DataNode读取它的副本,也会将被损坏的块通知给NameNode。
2. 写流程
- 客户端会带着文件路径向NameNode发送写入请求
- NameNode会去判断是否有权限,写入路径的父级目录是否存在,如都无误则发送可以写入的请求返回给客户端
- 客户端会将文件进行切分,然后上传block
- NameNode会根据DataNode的存储空间还有机架感知原理等返回该block块将要存储的DataNode的位置 ABC
- 客户端会去ABC三个DataNode节点上建立pipeline A-B B-C然后C建立完成后会将结果返 回给B B返回给A A返回给客户端
- 开始往A写入 依次进行流水线的复制
- 写入完后再去依次写入其他block块
- 都写入完成后会将写入完成的信息返回给NameNode
- NameNode存储该文件的各个block块的元数据信息
** 故障处理** - 如果DataNode在数据写入的时候发生故障,首先它会关闭管线,确认把队列中的所有数据包都添加回数据队列的最前端,确保故障节点下游的DataNode不会漏掉数据包。并且为存储在另一个正常DataNode的当前数据块指定一个新的标识,并把该标识传给NameNode,以便故障的DataNode在恢复后可以删除存储的部分数据块。然后从管线中删除故障DataNode,基于另外两个正常的DataNode构建一条新的管线,剩下的数据块写入管线中正常的DataNode,当NameNode注意到快副本数量不足的时候,就会在另一个节点上创建一个新的副本,后续的数据块继续正常处理。
说明: - 1、读取完一个 block 都会进行 checksum 验证,如果读取 DataNode 时出现错误,客户端会通知 NameNode,然后再从下一个拥有该 block 副本的DataNode 继续读。
- 2、read 方法是并行的读取 block 信息,不是一块一块的读取;NameNode 只是返回Client请求包含块的DataNode地址,并不是返回请求块的数据;