1,客户端发起rpc请求到NameNode,NameNode校验客户端权限.
2,NameNode收到请求之后会先校验文件是否存在,如果存在,那么会将这个文件所对应的block的存储地址放入一个队列(因为队列能保证顺序,顺序很重要,不然block块错误拼接就麻烦了)中返回给客户端
3,客户端收到队列之后,从队列中将每一个block对应地址来依次取出,从三个地址中找一个较近(经历的交换次数,内部近于跨机架近于跨机房,)的地址读取,和每一台DataNode地址之间建立pipeline,读取也是按照packet读取,packet还是64K,读取时候和写入不一样,读取时候是可以三个DataNode一起读取.
4,读取完一个block之后,对这个block进行一次checksum的验证,验证这个block的数据总量是否正确,如果不一致,说明这个block产生损坏,客户端会通知namenode,再从其他节点上读取该block,NameNode收到消息从新备份一次,发指令给这个DataNode让他把这个坏的删除
5, 客户端在读完这一批地址之后会向NameNode索要下一批地址,就是文件超级大情况下,可能性低.
6,将读取完的block进行合并操作,合并成一个文件
7,读完所有的block,客户端给NameNode发送消息,通知NameNode关闭文件就是关流
上面会疑虑为什么不是NameNode拿数据给客户端,而是客户端自己去DataNode拿数据,因为是并发的问题,如果数据很大,NameNode拿数据,给这个客户端之前,别的客户端就不能访问NameNode了,地址相对数据很小了,很快,为了高并发,和高吞吐.吞吐意思是这个节点一分钟能够读取10M数据,这个节点就是10M/分钟,一般情况下,高吞吐一般是高并发的,高并发的不一定是高吞吐的(发微信,很多人,并发高,但数据量很小)