HDFS 杂谈:数据读写原理
文件系统的核心流程是数据的存储与访问流程。本文将详细介绍 HDFS client 读写数据的原理及流程。
读流程
HDFS Client 调用 FileSystem 对象的 open 方法,创建一个 DistributedFileSystem 实例。
DistributedFileSystem 通过 rpc 向 NameNode 申请并获得所读文件的第一批 block 的 locations。同一个 block 按照副本数返回多个 locations,这些 locations 按照 DataNode 集群拓扑结构排序,距离 HDFS Client 近的排在前面。
步骤 1 和 2 完成后,DistributedFileSystem 实例会返回一个 FSDataInputStream 对象,该对象会被封装 DFSInputStream 对象,用于管理 DataNode 和 NameNode 数据流。此时 HDFS Client 调用 read 方法,DFSInputStream 便会找出步骤 2 排序第一的 DataNode 并连接。
数据通过 DFSInputStream 读取 DataNode 并源源不断的流向 HDFS Client。
如果第一块的 block 读完了,就会关闭指向第一块 block 的 DataNode 的连接,接着读取下一块 block。这些操作对 HDFS Client 来说是透明的,从 HDFS Client 的角度来看只是读一个持续不断的流。
如果第一批 block 都读完了, DFSInputStream 就会向 NameNode 申请并获取下一批 block 的 locations,然后继续循环步骤 4 和 5,直到所有的 block 都读完。这时 HDFS Client 就会关闭掉读取流。
如果在读数据的时候, DFSInputStream 和 DataNode 的通讯发生异常,就会尝试连接正在读的 block 的排序第二近的 DataNode。同时记录通讯异常的 DataNode,读取剩余的 blocks 时就会直接跳过该 DataNode。 重新读取后,DFSInputStream 会检查 block 的 crc(数据校验和)信息,如果发现 block 损坏,就会先报告到 NameNode,然后 DFSInputStream 再从其他的 DataNode 上重新读取该 block 的镜像。
写流程
HDFS Client 调用 FileSystem 对象的 open 方法,创建一个 DistributedFileSystem 实例。
DistributedFileSystem 通过 RPC 调用 NameNode 创建一个没有 blocks 关联的新文件。创建前, NameNode 会做各种校验,比如文件是否存在,HDFS Client 有无权限去创建等。如果校验通过, NameNode 就会创建新文件的元信息。
步骤 1 和 2 完成后,DistributedFileSystem 会返回 FSDataOutputStream 的对象。与读流程相似, FSDataOutputStream 被封装成 DFSOutputStream 对象,用于管理 NameNode 和 DataNode 的数据流。HDFS Client 开始写数据到 DFSOutputStream,DFSOutputStream 会把数据切成一个个小的 packet,并排成队列 data quene。
DataStreamer 对 DFSOutputStream 提供来的 data quene 进行处理。它先询问 NameNode 分配适合写入的几个 DataNode 及对应的 block 信息(比如副本数是 3,那么就让 NameNode 分配 3 个最适合的 DataNode),并把 DataNode 排成一个 pipeline。DataStreamer 把 packet 按 data quene 顺序写入到第一个 DataNode 的 block 中,第一个 DataNode 又把 packet 写入到第二个 DataNode 的 block 中,直到 pipeline 内所有 DataNode 写入完成。
DFSOutputStream 还有一个对列叫 ack quene,也是由 packet 组成,用于接收 DataNode 写入完成的响应及出现异常时的 packet 恢复。当 pipeline 中的所有 DataNode 按 ack quene 顺序都返回 ack 响应后,akc quene 才会把对应的 packet 包移除掉。
如果在写的过程中某个 DataNode 发生异常,会采取以下步骤处理:
关闭 pipeline;
为了防止丢包,ack quene 里的 packet 会同步到 data quene 里;
把产生错误的 DataNode 上当前在写但未完成的 block 删掉;
block 剩下的部分被写到剩下的两个正常的 DataNode 中;
NameNode 找到另外的 DataNode 去创建这个 block,并把数据复制进去。当然,这些操作对 HDFS Client 来说是无感知的。
完成写数据后,HDFS Client 调用 close 方法关闭写入流。
版权声明: 本文为 InfoQ 作者【罗小龙】的原创文章。
原文链接:【http://xie.infoq.cn/article/c88ac378b78c2077c344b3eb5】。文章转载请联系作者。
评论