【大数据存储与管理】分布式文件系统HDFS:06 HDFS的数据读写过程

【大数据存储与管理】分布式文件系统HDFS:06 HDFS的数据读写过程

【作者主页】Francek Chen
【专栏介绍】 ⌈ ⌈ ⌈大数据技术原理与应用 ⌋ ⌋ ⌋专栏系统介绍大数据的相关知识,分为大数据基础篇、大数据存储与管理篇、大数据处理与分析篇、大数据应用篇。内容包含大数据概述、大数据处理架构Hadoop、分布式文件系统HDFS、分布式数据库HBase、NoSQL数据库、云数据库、MapReduce、Hadoop再探讨、数据仓库Hive、Spark、流计算、Flink、图计算、数据可视化,以及大数据在互联网领域、生物医学领域的应用和大数据的其他应用。
【GitCode】专栏资源保存在我的GitCode仓库:https://gitcode.com/Morse_Chen/BigData_principle_application

文章目录


在介绍 HDFS 的数据读写过程之前,需要简单介绍一下相关的类。FileSystem 是一个通用文件系统的抽象基类,可以被分布式文件系统继承,所有可能使用 Hadoop 文件系统的代码都要使用到这个类。Hadoop 为 FileSystem 这个抽象类提供了多种具体的实现,DistributedFileSystem 就是 FileSystem 在 HDFS 中的实现。FileSystem 的 open()方法返回的是一个输入流 FSDataInputStream 对象,在 HDFS 中具体的输入流就是 DFSInputStream;FileSystem 中的 create()方法返回的是一个输出流 FSDataOutputStream 对象,在 HDFS 中具体的输出流就是 DFSOutputStream。

一、读数据的过程

importjava.io.BufferedReader;importjava.io.InputStreamReader;importorg.apache.hadoop.conf.Configuration;importorg.apache.hadoop.fs.FSDataInputStream;importorg.apache.hadoop.fs.FileSystem;importorg.apache.hadoop.fs.Path;publicclassChapter3{publicstaticvoidmain(String[] args){try{Configuration conf =newConfiguration(); conf.set("fs.defaultFS","hdfs://localhost:9000"); conf.set("fs.hdfs.impl","org.apache.hadoop.hdfs.DistributedFileSystem");FileSystem fs =FileSystem.get(conf);Path file =newPath("test");FSDataInputStream getIt = fs.open(file);BufferedReader d =newBufferedReader(newInputStreamReader(getIt));String content = d.readLine();// 读取文件一行System.out.println(content); d.close();// 关闭文件 fs.close();// 关闭hdfs}catch(Exception e){ e.printStackTrace();}}}
Configuration conf =newConfiguration(); conf.set("fs.defaultFS","hdfs://localhost:9000"); conf.set("fs.hdfs.impl","org.apache.hadoop.hdfs.DistributedFileSystem");FileSystem fs =FileSystem.get(conf);FSDataInputStream in = fs.open(newPath(uri));FSDataOutputStream out = fs.create(newPath(uri));

客户端连续调用 open()、read()、close()读取数据时,HDFS 内部的执行过程如下图1。

在这里插入图片描述

图1 HDFS读数据的过程

  1. 客户端通过 FileSystem.open() 打开文件,相应地,在 HDFS 中 DistributedFileSystem 具体实现了 FileSystem。因此,调用 open() 方法后,DistributedFileSystem 会创建输入流 FSData InputStream,对于 HDFS 而言,具体的输入流就是 DFSInputStream。
  2. 在 DFSInputStream 的构造函数中,输入流通过 ClientProtocal.getBlockLocations() 远程调用名称节点,获得文件开始部分数据块的保存位置。对于该数据块,名称节点返回保存该数据块的所有数据节点的地址,同时根据距离客户端的远近对数据节点进行排序;然后,DistributedFileSystem 会利用 DFSInputStream 来实例化 FSDataInputStream,并返回给客户端,同时返回数据块的数据节点地址。
  3. 获得输入流 FSDataInputStream 后,客户端调用 read() 方法开始读取数据。输入流根据前面的排序结果,选择距离客户端最近的数据节点建立连接并读取数据。
  4. 数据从该数据节点读到客户端;当该数据块读取完毕时,FSDataInputStream 关闭和该数据节点的连接。
  5. 输入流通过 getBlockLocations() 方法查找下一个数据块(如果客户端缓存中已经包含了该数据块的位置信息,就不需要调用该方法)。
  6. 找到该数据块的最佳数据节点,读取数据。
  7. 当客户端读取完数据的时候,调用 FSDataInputStream 的 close() 方法,关闭输入流。需要注意的是,在读取数据的过程中,如果客户端与数据节点通信时出现错误,就会尝试连接包含此数据块的下一个数据节点。

二、写数据的过程

importorg.apache.hadoop.conf.Configuration;importorg.apache.hadoop.fs.FSDataOutputStream;importorg.apache.hadoop.fs.FileSystem;importorg.apache.hadoop.fs.Path;publicclassChapter3{publicstaticvoidmain(String[] args){try{Configuration conf =newConfiguration(); conf.set("fs.defaultFS","hdfs://localhost:9000"); conf.set("fs.hdfs.impl","org.apache.hadoop.hdfs.DistributedFileSystem");FileSystem fs =FileSystem.get(conf);byte[] buff ="Hello world".getBytes();// 要写入的内容String filename ="test";// 要写入的文件名FSDataOutputStream os = fs.create(newPath(filename)); os.write(buff,0, buff.length);System.out.println("Create:"+ filename); os.close(); fs.close();}catch(Exception e){ e.printStackTrace();}}}

客户端向 HDFS 写数据是一个复杂的过程,这里介绍一下在不发生任何异常的情况下,客户端连续调用 create()、write() 和 close() 时,HDFS 内部的执行过程见图2。

在这里插入图片描述

图2 HDFS写数据的过程

  1. 客户端通过 FileSystem.create() 创建文件,相应地,在 HDFS 中 Distributed FileSystem 具体实现了 FileSystem。因此,调用 create() 方法后,DistributedFileSystem 会创建输出流 FSDataOutputStream,对于 HDFS 而言,具体的输出流就是 DFSOutputStream。
  2. 然后,DistributedFileSystem 通过 RPC 远程调用名称节点,在文件系统的命名空间中创建一个新的文件。名称节点会执行一些检查,比如文件是否已经存在,客户端是否有权限创建文件等。检查通过之后,名称节点会构造一个新文件,并添加文件信息。远程方法调用结束后,DistributedFileSystem 会利用 DFSOutputStream 来实例化 FSDataOutputStream,并返回给客户端,客户端使用这个输出流写入数据。
  3. 获得输出流 FSDataOutputStream 以后,客户端调用输出流的 write() 方法向 HDFS 中对应的文件写入数据。
  4. 客户端向输出流 FSDataOutputStream 中写入的数据会首先被分成一个个的分包,这些分包被放入 DFSOutputStream 对象的内部队列。输出流 FSDataOutputStream 会向名称节点申请保存文件和副本数据块的若干个数据节点,这些数据节点形成一个数据流管道。队列中的分包最后被打包成数据包,发往数据流管道中的第 1 个数据节点,第 1 个数据节点将数据包发送给第 2 个数据节点,第 2 个数据节点将数据包发送给第 3 个数据节点,这样,数据包会流经管道上的各个数据节点。
  5. 因为各个数据节点位于不同的机器上,数据需要通过网络发送。因此,为了保证所有数据节点的数据都是准确的,接收到数据的数据节点要向发送者发送“确认包”(ACK Packet)。确认包沿着数据流管道逆流而上,从数据流管道依次经过各个数据节点并最终发往客户端,当客户端收到应答时,它将对应的分包从内部队列移除。不断执行 3~5 步,直到数据全部写完。
  6. 客户端调用 close() 方法关闭输出流,此时开始,客户端不会再向输出流中写入数据,所以,当 DFSOutputStream 对象内部队列中的分包都收到应答以后,就可以使用 ClientProtocol.complete() 方法通知名称节点关闭文件,完成一次正常的写文件过程。

小结

HDFS 读写数据时,读数据通过 FileSystem.open() 创建DFSInputStream,获取数据块位置,选择最近数据节点读取,读完关闭连接并查找下一数据块;写数据则通过 FileSystem.create() 创建 DFSOutputStream,远程调用名称节点创建文件,写入数据时分包放入队列,形成数据流管道传输,数据节点发送确认包,全部写完客户端调用 close() 关闭输出流,通知名称节点关闭文件,从而完成 HDFS 数据正常读写过程。

欢迎 点赞👍 | 收藏⭐ | 评论✍ | 关注🤗

Read more

从 0 到 1 的 ORM 指南:Python+SQLAlchemy+MySQL

作为 Python 生态中最强大的 ORM 框架,SQLAlchemy 几乎是中大型 Python 项目的 “标配”—— 它能帮你用 Python 类操作 MySQL 数据库,彻底告别原生 SQL 的繁琐。 本文针对0 基础小白,从环境搭建→核心概念→CRUD 实战→关系映射,一步步讲清如何用 SQLAlchemy 连接 MySQL。全程代码可复制,每一行都有解释,目标是让你 “学完就能用”。 一、前置准备:环境搭好再开始 在写代码前,必须先搞定 3 件事:安装 MySQL、安装 Python 库、配置连接。 1. 安装 MySQL(新手推荐用

By Ne0inhk

DeepSeek-R1-Distill-Qwen-1.5B代码实例:Python API调用完整示例

DeepSeek-R1-Distill-Qwen-1.5B代码实例:Python API调用完整示例 1. 引言 1.1 业务场景描述 随着大模型在边缘设备和轻量化部署场景中的需求日益增长,如何高效地将高性能语言模型集成到实际应用中成为工程落地的关键挑战。DeepSeek-R1-Distill-Qwen-1.5B作为一款经过知识蒸馏优化的轻量级模型,在保持较强推理能力的同时显著降低了资源消耗,适用于对延迟敏感、算力受限的应用环境。 1.2 痛点分析 传统大模型部署往往面临显存占用高、推理延迟长、服务启动复杂等问题,尤其在T4或A10等中低端GPU上难以实现实时响应。此外,API接口不统一、调用方式多样也增加了开发成本。因此,亟需一套标准化的服务部署与调用方案来提升开发效率。 1.3 方案预告 本文将详细介绍如何使用vLLM框架部署 DeepSeek-R1-Distill-Qwen-1.5B 模型,并通过OpenAI兼容的Python客户端进行本地API调用。涵盖模型服务启动、日志验证、同步/流式对话测试等关键环节,提供可直接运行的完整代码示例,帮助开发者快速完成模型集成

By Ne0inhk
【Python 速览 】 —— 课前甜点,打开你的味蕾

【Python 速览 】 —— 课前甜点,打开你的味蕾

欢迎来到ZyyOvO的博客✨,一个关于探索技术的角落,记录学习的点滴📖,分享实用的技巧🛠️,偶尔还有一些奇思妙想💡 本文由ZyyOvO原创✍️,感谢支持❤️!请尊重原创📩!欢迎评论区留言交流🌟 个人主页 👉 ZyyOvO 本文专栏➡️Python 算法研究所 各位于晏,亦菲请阅 * 前言 * 课前甜点 * Python解释器 * 唤出解释器 * 传入参数 * 交互模式 * 解释器的运行环境 * 源文件的字符编码 * Python注释 * Python用作计算器 * 数字 * 文本 * 列表 * 走向编程的第一步 * 扩展阅读 * 本文小结 前言 Python 是一门易于学习、功能强大的编程语言。它提供了高效的高级数据结构,还能简单有效地面向对象编程。Python 优雅的语法和动态类型以及解释型语言的本质,使它成为多数平台上写脚本和快速开发应用的理想语言。 Python 官网 上免费提供了 Python 解释器和扩展的标准库,包括源码和适用于各操作系统的机器码形式,并可自由地分发。Python 官

By Ne0inhk
初学者如何用 Python 写第一个爬虫?

初学者如何用 Python 写第一个爬虫?

?? 欢迎来到我的博客! 非常高兴能在这里与您相遇。在这里,您不仅能获得有趣的技术分享,还能感受到轻松愉快的氛围。无论您是编程新手,还是资深开发者,都能在这里找到属于您的知识宝藏,学习和成长。 ?? 博客内容包括:Java核心技术与微服务:涵盖Java基础、JVM、并发编程、Redis、Kafka、Spring等,帮助您全面掌握企业级开发技术。大数据技术:涵盖Hadoop(HDFS)、Hive、Spark、Flink、Kafka、Redis、ECharts、Zookeeper等相关技术。开发工具:分享常用开发工具(IDEA、Git、Mac、Alfred、Typora等)的使用技巧,提升开发效率。数据库与优化:总结MySQL及其他常用数据库技术,解决实际工作中的数据库问题。Python与大数据:专注于Python编程语言的深度学习,数据分析工具(如Pandas、NumPy)和大数据处理技术,帮助您掌握数据分析、数据挖掘、机器学习等技术。数据结构与算法:

By Ne0inhk