HDFS 读写流程简述

本文详细介绍了HDFS客户端读写文件的过程。读流程包括查询元数据、获取DataNode地址及读取数据块等步骤;写流程则涉及请求上传、获取目标DataNode服务器列表、建立pipeline并传输数据块等内容。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

参考:https://blog.youkuaiyun.com/litianxiang_kaola/article/details/70984777

          https://blog.youkuaiyun.com/zhanglh046/article/details/78547490

一、客户端读流程简述


1.namenode通信查询元数据,找到文件块所在的datanode服务器,HDFS客户端首先调用DistributedFileSystem

.open方法打开HDFS文件,底层会调用ClientProtocal.open方法,返回一个用于读取的HdfsDataInputStream对象。

2.从NameNode获取DataNode地址:在构造DFSInputStream的时候,对调用ClientPortocal.getBlockLocations方法向NameNode获取该文件起始位置数据块信息。NameNode返回的数据块的存储位置是按照与客户端距离远近排序的。所以DFSInputStream可以选择一个最优的DataNode节点,然后与这个节点建立数据连接读取数据块。

3.连接到DataNode读取数据块: HDFS客户端通过调用DFSInputSttream从最优的DataNode读取数据块,数据会以数据包packet形式从DataNode以流式接口传送到客户端,当达到一个数据块末尾的时候,DFSInputStream就会再次调用ClientProtocal.getBlockLoctions获取下一个数据块的位置信息,并建立和这个新的数据块的最优节点之间的连接,然后HDFS继续读取数据块。

(客户端读取数据块的时候,很有可能这个数据块的DataNode出现异常,也就是无法读取数据。这时候DFSInputStream会切换到另一个保存了这个数据块副本的DataNode,然后读取数据。另外,数据块的应答不仅包含了数据块还包含了校验值,HDFS客户端收到数据应答包的时候,会对数据进行校验,如果校验错误,也就是DataNode这个数据块副本出现了损坏,HDFS 客户端会通过ClientProtocal.reportBadBlocks向NameNode汇报这个损坏的数据块副本,同时DFSInputStream会尝试从其他DataNode读取这个数据块)

4.客户端关闭输入流

二、客户端写流程简述


1.和namenode通信请求上传文件,namenode检查目标文件是否已存在,父目录是否存在

2.namenode返回是否可以上传

3.client请求第一个 block该传输到哪些datanode服务器上

4.namenode返回3个datanode服务器ABC

5.client请求3台dn中的一台A上传数据(本质上是一个RPC调用,建立pipeline),A收到请求会继续调用B,然后B调用C,将真个pipeline建立完成,逐级返回客户端

6.client开始往A上传第一个block(先从磁盘读取数据放到一个本地内存缓存),以packet为单位,A收到一个packet就会传给B,B传给C;A每传一个packet会放入一个应答队列等待应答

7.当一个block传输完成之后,client再次请求namenode上传第二个block的服务器。


### HDFS 读写流程详解 #### HDFS 写数据流程 当客户端需要向 HDFS 中写入数据时,整个流程可以分为以下几个部分: 1. **请求初始化** 客户端通过 RPC 请求 NameNode,告知其要上传的文件名及相关信息。NameNode 验证客户端是否有写权限,并检查目标路径是否存在冲突[^4]。 2. **文件切片** 如果验证通过,客户端将文件按照预设大小(默认为 128MB 或 256MB)分割成多个 Block 块[^4]。 3. **分配 DataNode 列表** 对于每一个 Block,客户端再次联系 NameNode,询问当前 Block 应该存储在哪几个 DataNode 上。NameNode 根据副本策略(通常为三副本)、机架感知原则以及负载均衡情况返回一组 DataNode 地址列表[^4]。 4. **创建 Pipeline** 客户端根据返回的 DataNode 列表,依次与这些节点建立连接,形成一条传输管道 (Pipeline)[^4]。 5. **数据流式传输** 数据从客户端流向第一个 DataNode,随后逐级传递至后续节点。与此同时,每个接收方都会发送 ACK 确认消息回传给前一环节,最终到达客户端表示成功完成此阶段的任务。 6. **重复以上步骤直到结束** 当一个 Block 成功写入后,继续处理下一个 Block,直至整份文件全部被拆解并分布存储完毕为止[^4]。 ```python def hdfs_write_process(file_path): client_request_name_node(file_path) blocks = split_file_into_blocks(file_path) for block in blocks: data_nodes_list = get_data_nodes_from_name_node(block) pipeline = establish_pipeline(data_nodes_list) send_block_to_first_datanode(block, pipeline) wait_for_acknowledgement(pipeline) finalize_upload() ``` --- #### HDFS 读数据流程 相对于复杂的写操作而言,HDFS 的读取逻辑相对简单明了一些: 1. **定位 Block 元数据** 用户提交读取需求之后,Client 向 NameNode 发起查询请求,后者依据内部维护的全局视图提供关于所需文件的所有 Block 及对应存放地址的信息[^3]。 2. **选取最优副本源** 接下来,基于地理位置或者网络拓扑结构等因素考量,挑选最接近自身的那个副本作为优先访问对象;假设存在同属单一 Rack 下的情况,则直接选用此类资源以减少跨网通信开销[^3]。 3. **直连 DataNode 获取内容** 找准具体负责保存某段特定区间资料的那个实际物理机器即 DataNode ,然后由 Client 主动发起 TCP 连接并与之交换必要的认证参数后再正式索取所求字节序列[^3]。 4. **拼接重组原始文档** 收集齐各个分散片段以后,在内存里依照原先设定好的次序组装还原成为完整的单体档案供应用程序调用使用。 ```python def hdfs_read_process(file_path): file_metadata = request_file_metadata_from_name_node(file_path) sorted_blocks = sort_blocks_by_proximity(file_metadata['blocks']) content_parts = [] for block_info in sorted_blocks: closest_dn = find_closest_datanode(block_info['locations']) part_content = fetch_part_content(closest_dn, block_info['offset'], block_info['length']) content_parts.append(part_content) full_content = concatenate_parts(content_parts) return full_content ``` --- #### 关键特性说明 - **机架感知机制**:为了提高系统的可靠性和性能表现,HDFS 设计了一套独特的算法用来决定如何合理安排各份拷贝的具体安放地点——这就是所谓的“机架感知”。它不仅考虑到了不同服务器之间的相互关系还兼顾了它们所属的不同子网环境下的差异性影响因素从而达到最佳效果[^1]^。 - **高可用保障措施**:即使某个单独组成部分发生故障也不会轻易导致整体服务中断现象的发生因为还有另外两处地方保留着完全一致的内容可供随时切换替代使用所以能够有效抵御各种意外状况带来的冲击风险[^2]^. ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值