HDFS 数据流
客户端和与之交互的HDFS,namenode,datanode之间的数据流
1. 文件读取
1) 客户端调用FileSystem的open()方法打开文件,对于HDFS,是一个DistributedFileSystem的实例
2) DistributedFileSystem的实例通过RPC调用namenode,namenode根据映射关系返回存有文件块副本的datanode地址,datanode根据与客户端的距离排序(网络拓扑),如果本身也是datanode且存有文件块,则客户端从本地获取副本
3) DistributedFileSystem返回一个FSDataInputStream对象给客户端以便读取数据,FSDataInputStream封装了DFSInputStream,这个类管理者datanode和namenode的I/O,客户端对DFSInputStream反复调用read()方法,将数据从datanode传输到客户端
4) 块读取完毕后,DFSInputStream关闭与该datanode的连接,寻找下一个块所在的最佳datanode,重复读取,一直到读取完毕,调用FSDataInputStream的close()
DFSInputStream的作用
1) 管理namenode和datanode的I/O
2) 存储namenode告知的块位置
3) 如果遇到与datanode通信错误,则连接另一个最近的有副本的datanode,并记录故障节点,不再与它通信
4) 校验datanode块的完整性,如果有问题,告诉namenode,并从其他节点读取副本
2. 文件写入
1) 客户端使用DistributedFileSystem对象调用create()创建一个新文件
2) 对namenode进行RPC调用在文件系统命名空间新建文件,namenode执行检查确认文件不存在且客户端有新建文件权限
3) DistributedFileSystem向客户端返回一个FSDataOutputStream对象,FSDataOutputStream封装了一个DFSOutputStream对象,负责与namenode和datanode通信
4) 写入数据时
> DFSOutputStream将数据分为数据包,写入“数据队列”(data queue)
> DataStreamer挑选出适合存储副本的一组datanode,并向namenode请求分配新的数据块
> 存储副本的datanode形成管线,DataStreamer将数据包流式传输到第一个datanode,这个datanode通过管线将数据包传递给下一个datanode,依次到结束
> DFSOutputStream维护确认队列(ack queue),收到所有datanode确认信息后,数据包从确认队列删除
5) 客户端完成数据写入后,调用FSDataOutputStream的close()方法,将剩余数据包全部写入datanode管线,并等待确认信息,最后告知namenode文件写入完成
如果datanode在写入时发生故障
1) 关闭管线,把队列中的所有数据包(共同组成一个块)添加回数据队列的最前端,确保下游的datanode不漏掉任何一个数据包
2) 将存储了正确数据块信息的datanode添加标识,把标识传给namenode,故障节点在恢复后删除存储的部分数据块,在管线添加一个新的datanode,替换故障datanode