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

Ubuntu22.04.5安装ROS2教程(使用鱼香ROS工具)

1.ROS2安装(使用鱼香ROS工具) 1.1.准备 建议准备一个干净、换好源的 ubuntu 20.04 以上的虚拟机(建议清华源),我的是 Ubuntu 22.04 ,本教程也适用其他 ROS2 版本。 查看ubuntu 版本 lsb_release -a 根据自己的 ubuntu 的版本选择 ROS2 版本 (我的是 ubuntu 22.04 所以对应ROS2版本为 humble) 要使用小鱼的一键安装系列,需要下载一个鱼香大佬写的脚本,然后执行这个脚本,进行ROS的安装与环境的配置 下载脚本并执行脚本 wget http://fishros.com/install -O fishros &&

By Ne0inhk
Linux 进程信号深度解析:从内核机制到实操应用全指南----《Hello Linux!》(15)

Linux 进程信号深度解析:从内核机制到实操应用全指南----《Hello Linux!》(15)

文章目录 * 前言 * 信号的初步认识 * 捕获信号的办法 * 键盘数据输入给内核的原理 * core dump * 信号的产生 * 系统调用 * 异常 * 软件条件 * 信号的发送 * 信号的保存 前言 在 Linux 系统中,进程信号是一套高效的 “异步通信机制”—— 它如同给进程发送的 “通知”,能够打断进程的正常执行流程,触发预设的处理动作。小到ctrl+c终止前台进程,大到异常崩溃时的核心转储(core dump)、进程间的紧急通知,信号贯穿了 Linux 进程管理的方方面面。 信号的本质是内核向进程传递事件的 “软件中断”,其生命周期涵盖 “产生→发送→保存→递达→处理” 五大环节,背后依赖block(阻塞)、pending(未决)、handler(处理函数)三张核心表的协同工作。本文将从基础认知出发,层层拆解进程信号的核心逻辑:

By Ne0inhk

实时获取 Google 相关股票新闻并完成自动化总结

@TOC 🌈你好呀!我是 是Yu欸🚀 感谢你的陪伴与支持~ 欢迎添加文末好友🌌 在所有感兴趣的领域扩展知识,不定期掉落福利资讯(*^▽^*) 写在最前面 版权声明:本文为原创,遵循 CC 4.0 BY-SA 协议。转载请注明出处。 本次演示围绕 Bright Data 与 Haystack 的集成实操 展开,完整展示了从获取 Bright Data API 密钥、创建 SERP API 与 Web Unlocker API Zone,到在 Haystack 中封装为 Tool 并接入 Agent 的全流程; 同时通过实际示例,演示了 AI Agent 在推理过程中按需调用搜索与网页抓取能力,

By Ne0inhk
Flutter 三方库 adb_dart 的鸿蒙化适配指南 - 实现纯 Dart 的 ADB 协议通信、远程控制手机与自动化调试脚本开发

Flutter 三方库 adb_dart 的鸿蒙化适配指南 - 实现纯 Dart 的 ADB 协议通信、远程控制手机与自动化调试脚本开发

欢迎加入开源鸿蒙跨平台社区:https://openharmonycrossplatform.ZEEKLOG.net Flutter 三方库 adb_dart 的鸿蒙化适配指南 - 实现纯 Dart 的 ADB 协议通信、远程控制手机与自动化调试脚本开发 前言 在 Flutter for OpenHarmony 的开发辅助工具中,有时我们需要直接从应用内部与 Android 设备(作为分布式设备的一部分)进行调试交互,或者构建一个纯 Dart 的桌面端调试器。adb_dart 是一个实现了完整 ADB(Android Debug Bridge)通信协议的 Dart 库。它允许你在不依赖外部 adb 二进制文件的情况下,直接通过 Socket 发送指令。本文将讲解如何在鸿蒙端利用该库构建跨平台的调试方案。 一、原理解析

By Ne0inhk