一、常用概念
1、fsimage里存放元数据:不是原始数据,包含HDFS文件系统的所有目录和文件inode的序列化信息(id、类型、目录、所属用户、用户权限、时间戳、哪一个块,第几个备份,存储在哪一个DN里……)
2、DataNode:存储数据块,执行MapReduce计算
3、yarn:资源调度,管钱的,财务。一般来说,ResourceManager在NN上,调度的机制是心跳机制,在服务启动时,在所有的RM和NM之间构建一个通道,定期的在RM NM之间做数据汇报机制。NN和DN之间是没有关系的,通过yarn来进行发布任务,调度资源。
4、NameNode:管理者,做资源管理,协调资源,需要借助yarn,类似管账的,会计;需要借助yarn,通过心跳机制和DN进行联系
5、RandomAccessFileInputStream随机读取,用于断点续传,文件切割
6、SecondaryNameNode:辅助NameNode做日志合并,并不是NN的热备;
二、HDFS写入过程:
1、client 发起请求:通过DFS向NN请求
- 文件的读写都是通过DFS来实现的,首先要创建一个DFS对象
2、NameNode 确认:目录存在、用户没有操作权限 return false,否则return true
- 是一个验证的过程,可不可以传,若目录存在,或者用户权限不够,就不能传
3、client 切分文件并请求第一个Block要写入的DN列表
- 确定可以传输后,client将文件切成n个128M的Block
- 向谁请求:client向NN请求第1个Block的存储DN列表
4、NN 返回DN列表
- 假如返回dn1,dn2,dn3(BlockId:主机,端口号,存放的目录)
5、client 写入
- a. FSDOS向dn1请求写入
- b. dn1请求dn2,dn2请求dn3,分别建立pipeline管道
- c. dn3响应dn2,dn2响应dn1,dn1响应client
- d. Block传输
- d.1 client读取第一个Block并以Packet(64k)为单位传输,dn1每收到一个Packet会建立等待应答队列,并逐级传输给dn2,dn3
- d.2 dn3,dn2,d,1逐级应答,并将结果反馈给client
- d.3 重复d.1~d.2直至block传输完成 - f. 关闭FSDOS
6、client发送complete给NN
- 传输完成并关闭FSDOS后,也就是一个文件块传完,会反馈给NN,写入日志后再由SNN合并
7、重复3~6直至所有Block传输完成
注:当一个Block块成功传输完以后,从最后一个DataNode开始,依次从管道返回ACK队列,到客户端。 客户端会在自己内部维护着一个ACK队列,跟返回来的ACK队列进行匹配,只要有一台DataNode写成功,就认为这次写操作是完成的
三、HDFS读过程:
1、client创建DFS
- DFS dfs = FileSystem.open(),调用FileSystem.open()方法,获取到DistributedFileSystem实例
2、DFS向NN请求RPC获取【文件开始部分或全部】Block有序列表
- 列表按距离client的距离升序排序
- 返回的列表里的每个Block都包含DN地址,如果client就是DN,则本地读取
3、DFS向client返回一个支持文件定位的输入流对象FSDIS(FSDataInputStream),用于客户端读取数据
- FSDIS中包含一个DFSIS(DFSInputStream)对象,用来管理DN和NN之间的IO
- DN中数据缺失或者下载一部分之后任务失败,则可以通过DFSInputStream联系NN求助 NN借助yarn找到距离最近的另一个备份节点
- 将未完成的下载任务迁移到该节点,并通过【支持文件定位】的输入流对象FSDIS进行【续传】
4、client调用FSDataInputStream的read()方法找到离client最近的DN,并连接DN
- 选哪个DataNode,根据拓扑图计算距离,选最近的
5、DFSIS依次读取一个批次的Block
- a. 读取包含文件第一个Block的最近DN地址
- b. 重复调用read()方法,直至第一个Block读取完成
- c. 关闭DN连接
- d. 重复a~c直至第一个批次的Block全部读取完成
6、重复2~5,直到所有批次的Block全部读取完成
7、关闭DFSIS,FSDIS,DFS
注:客户端读取完Block块信息以后,会计算出一个校验和跟读取过来的校验和进行对比,如果能匹配上,就说明正确。如果匹配不上,就从其他节点上读取Block块
注2:FileSystem的open方法,创建DFS实例,DistributeFileSystem类中有网络通信连接的方法,因此可以发起RPC请求。然后DFS通过open方法创建一个支持文件定位的FSDataInputStream(实现了seekable和positionReadable接口)对象,而这个对象的入口参数是DFSInputStream。在调用FSDataInputStream的read()方法读数据时,实际上是调用了DFSInputStream的read()方法,具体的读的过程是DFSInputStream读的,而FSDataInputStream起到的作用是定位文件位置