【大数据存储与管理】分布式文件系统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

Flutter 三方库 flutter_app_packager 的鸿蒙化适配指南 - 在鸿蒙系统上构建极致、自动化、全平台的桌面端安装包打包与工程分发引擎

欢迎加入开源鸿蒙跨平台社区:https://openharmonycrossplatform.ZEEKLOG.net Flutter 三方库 flutter_app_packager 的鸿蒙化适配指南 - 在鸿蒙系统上构建极致、自动化、全平台的桌面端安装包打包与工程分发引擎 在鸿蒙(OpenHarmony)系统的桌面端适配(Ohos PC Mode)以及为鸿蒙应用构建配套的 PC 端管理工具(macOS/Windows/Linux 版辅助工具)时,如何通过一套 Dart 代码或命令行指令,即可瞬间将 Flutter 应用转化为原生的 .dmg, .exe 或 .deb 安装包?flutter_app_packager 为开发者提供了一套工业级的、基于 Dart 的自动化打包封装方案。本文将深入实战其在全平台分发工程中的应用。 前言 什么是

从Cgroups精准调控到LXC容器全流程操作​:用pidstat/stress测试Cgroups限流,手把手玩转Ubuntu LXC容器全流程​

从Cgroups精准调控到LXC容器全流程操作​:用pidstat/stress测试Cgroups限流,手把手玩转Ubuntu LXC容器全流程​

本篇摘要 本文围绕Linux资源管理与容器技术展开,通过pidstat监控、stress压测演示Cgroups对CPU/内存的精准控制,并实战Ubuntu 22.04下LXC容器的创建、隔离及销毁,验证资源限制与轻量级虚拟化能力。 欢迎拜访:点击进入博主主页 本篇主题:Docker之cgroups+lxc操作详解 制作日期:2025.08.28 隶属专栏:点击进入所属Docker专栏 一. Cgroups资源控制 pidstat与stress pidstat 1. 所属工具集:是 sysstat 工具集的一部分。 2. 功能:监控全部或指定进程的 CPU、内存、线程、设备 IO 等系统资源占用情况。首次采样显示自系统启动以来的统计,后续采样显示自上次命令以来的统计,可指定采样次数和时间。 3. 语法:pidstat [选项] [时间间隔] [次数] 4. 常用参数:

【Linux】统信UOS服务器安装MySQL8.0(RPM)

【Linux】统信UOS服务器安装MySQL8.0(RPM)

目录 一、下载安装包 二、安装MySQL 2.1hive适配 2.2ranger适配 3.2DolphinScheduler适配 一、下载安装包 官网下载安装包:MySQL :: MySQL Downloads 选择社区版本下载 点击MySQL Community Server 选择对应系统的MySQL版本号 统信1060a 操作系统对应 redhat8 ,我们下载对应MySQL RPM包 选择直接下载 二、安装MySQL ## 解压 tar -xvf mysql-8.0.40-1.el8.x86_64.rpm-bundle.tar ## 安装 yum install -y net-tools perl libaio rpm -ivh

Flutter 三方库 http_mock_adapter — 赋能鸿蒙应用开发的高效率网络接口 Mock 与自动化测试注入引擎(适配鸿蒙 HarmonyOS Next ohos)

Flutter 三方库 http_mock_adapter — 赋能鸿蒙应用开发的高效率网络接口 Mock 与自动化测试注入引擎(适配鸿蒙 HarmonyOS Next ohos)

欢迎加入开源鸿蒙跨平台社区:https://openharmonycrossplatform.ZEEKLOG.net。 Flutter for OpenHarmony:Flutter 三方库 http_mock_adapter — 赋能鸿蒙应用开发的高效率网络接口 Mock 与自动化测试注入引擎(适配鸿蒙 HarmonyOS Next ohos) 前言 在华为鸿蒙(OpenHarmony)生态的应用开发中,前后端并行开发(Parallel Development)是常态。当后端 API 还在设计或局域网联调环境不稳定时,如果客户端开发者只能干等着真实数据,开发进度将会大打折扣。此外,在进行健壮性测试(如模拟服务器 500 错误、超时、返回脏数据)时,真实服务器往往难以配合。 http_mock_adapter 是一款专为 Dio 打造的高性能 Mock 拦截器。