#详细步骤
第1步:客户端初始化写入请求
应用程序通过 FileSystem.get(conf) 获取一个 DistributedFileSystem 实例。
客户端调用 DistributedFileSystem.create() 方法来在HDFS上创建一个新文件。
第2步:NameNode创建文件元数据
DistributedFileSystem 通过 RPC 调用连接到 NameNode。
NameNode 收到请求后,执行以下操作:
检查:确保文件不存在,并且客户端有创建权限。
创建元数据:在命名空间中创建该文件的元数据(注意:此时文件还没有任何数据块)。
NameNode 返回一个 FSDataOutputStream 对象给客户端。这个输出流将处理数据写入。
第3步:写入数据 - 管道建立
客户端开始向 FSDataOutputStream 写入数据。
数据首先被缓存在客户端内部的一个数据队列中。
FSDataOutputStream 有一个独立的线程 DataStreamer,它负责:
当数据队列中有数据时,DataStreamer 会请求 NameNode 分配一个新的数据块,并返回一组用于存储该数据块副本的 DataNodes 列表(比如3个节点)。
DataStreamer 根据 NameNode 返回的 DataNode 列表,建立一个写入管道(Pipeline)。
第4步:写入数据 - 管道传输
数据被分割成多个数据包(默认64KB)。每个数据包被发送到管道中的第一个 DataNode。
第一个 DataNode 接收数据包,将其存储到本地,并同时将数据包转发给管道中的第二个 DataNode。
第二个 DataNode 做同样的事情,接收并存储,然后转发给第三个 DataNode。
数据包在管道中以流式方式传输,而不是等待整个文件传输。
第5步:确认机制
当数据包成功写入管道中的所有 DataNode 后,最后一个 DataNode 会发送一个确认包(ACK),该确认包沿着管道反向传递回客户端。
客户端收到确认后,表示该数据包已成功写入。同时,每个 DataNode 都会定期向 NameNode 发送块报告,
但此时 NameNode 并不实时跟踪每个数据包的写入。
第6步:容错处理
如果在写入过程中,管道中的某个 DataNode 发生故障:
管道会立即关闭。
客户端会收到通知,然后将剩余的数据包重新写入到管道中新的 DataNode 集合(由 NameNode 重新分配,并排除故障节点)。
为了保证一致性,故障节点上已经写入的部分数据会被丢弃。
HDFS 确保只要写入成功(即客户端收到确认),数据就已经被可靠地写入到多个节点上。
第7步:数据块切换
当当前数据块被写满(默认达到128MB),客户端会再次请求 NameNode 分配新的数据块,并建立新的管道,重复上述过程。
第8步:完成写入
当客户端完成所有数据的写入后,调用 close() 方法关闭输出流。
在关闭过程中,客户端会将最后的剩余数据包刷新到管道中,并等待确认。
然后,客户端通知 NameNode 文件写入完成。此时,NameNode 会提交文件的元数据(包括文件由哪些块组成,
每个块的位置等)。如果 NameNode 在提交前重启,则该文件可能会丢失。
关键特性与设计哲学
1. 数据可靠性
通过多副本机制和确认机制,确保数据被持久化到多个节点后才向客户端返回成功。
2. 流水线复制
数据包沿着管道顺序传输,而不是同时发送到所有节点,这有效利用了网络带宽。
3. 容错与恢复
写入过程中能够自动处理 DataNode 故障,并重新建立管道,保证写入的持续进行。
4. 客户端主导
整个写入过程由客户端驱动,NameNode 只负责元数据管理和分配数据块,不参与实际的数据传输,避免了单点瓶颈。
代码示例视角
从代码层面看,这个过程对开发者来说非常简单:
java
// 1. 获取HDFS文件系统实例
Configuration conf = new Configuration();
FileSystem fs = FileSystem.get(conf);
// 2. 创建一个文件路径,HDFS在背后完成了所有复杂的步骤
Path filePath = new Path("/user/data/output.txt");
FSDataOutputStream out = fs.create(filePath);
// 3. 写入数据
String data = "Hello, HDFS!";
out.writeUTF(data); // 背后是复杂的数据包、管道、确认等过程
// 4. 关闭流,此时才确保数据被完整写入并持久化
out.close();
fs.close();
总结
HDFS 的写数据流程是一个精心设计的、分布式、容错、高效的过程。它通过将 NameNode 的集中式元数据管理
和 DataNode 的分布式数据存储 分离,并结合 客户端驱动的流水线复制,完美地支撑了大数据场景下的海量数据写入需求。
其核心优势在于:高吞吐量的数据写入、透明化的容错以及对于大文件的优化。
11-24
647
647
01-30
471
471
09-06
1441
1441
11-24
2719
2719

被折叠的 条评论
为什么被折叠?



