1. HDFS
HDFS是以流式数据访问模式来存储超大文件的分布式文件系统,能忍受节点故障且不丢失任何数据。
1.1 HDFS读写流程
1.1.1 读流程
-
Open:客户端通过 DistributedFileSystem 调用 open() 来打开它希望读取的文件。
-
Get Black Locations:DistributedFileSystem 通过RPC来调用NameNode,来得到文件起始块的位置。对于每一个数据块,NameNode都会返回存有该块地址的DataNode地址。
-
Read:DFSInputStream 是由 FSDataInputStream 封装的对象,负责 DataNode 和 NameNode 之间的通信。客户端调用 DFSInputStream 的read()方法。
-
Read:FSInputStream 会连接距离最近的文件中第一个块所在的 DataNode。通过对数据流反复调用 read() 方法,数据就从DataNode传输到客户端。
-
Read:到达块的末端时,DFSInputStream 关闭与这个 DataNode 的连接,然后寻找下一个块的最佳(近)DataNode。
-
Close:客户端完成读取后,调用FSDataInputStream 的close()方法
遇到故障怎么办?
在读取数据时,如果DFSInputStream在于DataNode通信时遇到错误,会尝试从这个块的另外一个最邻近的DataNode读取数据,也会记录故障DataNode以保证以后不会反复读取该节点上后续的块。DFSInputStream也会通过校验和确认数据是否完整,如果发现块有损坏,会从其他DataNode读取其复本,同时通知给NameNode。
1.1.2 写流程
-
Open:客户端通过对 DistributedFileSystem 调用 create() 来新建文件。
-
Create:DistributedFileSystem 会对 NameNode 进行 RPC 通信,从而在 NameSpace 中新建一个文件。 NameNode会执行不同的检查来确保这个文件不存在以及客户端有新建文件的权限。NameNode 会为创建新文件来记录一条记录。
-
Write :DFSOutputStream 是由 FSDataOutputStream 封装的对象,负责 DataNode 和 NameNode 之间的通信。DFSOutputStream将数据分为一个个的数据包,写入内部队列,也就是Data Queue。
-
Write Packet :DataStreamer 处理数据队列,挑选出适合存储数据复本的一组 DataNode,以此来要求 NameNode 分配新的数据块。这样一组 DataNode 构成一个 Pipeline,随后数据包开始流式传输,先到第一个 DataNode,它存好之后发送到第二个 DataNode,第二个存好之后发给第三个(假设复本数为3)
-
Ack Packet :DFSOutputStream 维护着一个内部的数据包队列来等待 DataNode 收到确认回执,这个队列称为 Ack Queue。等收到所有的 DataNode 的确认信息,该数据包会从确认队列删掉。
-
Close/Complete :客户端完成数据的写入后,对数据流调用 close() 方法。剩余的所有数据包都会写入 DataNode Pipelines,并联系到 NameNode 告知其文件写完之前,等待确认,也就是重复以上步骤直到完成。
遇到故障怎么办?
关闭Pipeline,吧队列中的所有数据包都添加回数据队列的最前端,以保障故障节点下游的DataNode不会遗漏任何一个数据包。为存储在另一个正常DataNode的当前数据块指定一个新的标识,并将该标识床第给NameNode,以保障故障DataNode在恢复之后可以删除存储的的部分数据块。从pipeline中删除故障的DataNode,基于两个正常的DataNode构建一条新的管线。余下的数据块写入Pipeline中正常的DataNode。
NameNode注意到块的复本量不足时,会在另一个节点上创建一个新的复本。后续的数据块继续正常接受处理。
如果是多个DataNode呢?
这种情况比较少见,但只要有一个DataNode写进去,操作就会成功,并且这个块会在集群中异步复制,指导达到目标的复本数为止。