HDFS简介

一、什么是HDFS

HDFS全称是Hadoop Distributed File System,简称HDFS。这是一个分布式文件系统,当数据规模大小超过一台物理计算机的存储能力时,就有必要进行分区并存储到若干台物理计算机上。管理网络中跨多台计算机的文件系统称为分布式文件系统。

Hadoop的文件系统是一个抽象的概念,java的抽象类是org.apache.hadoop.fs.FileSystem,在创建一个FileSystem的时候,FileSystem使用文件系统URI的Schema作为查询配置或者SPI寻找实现类(类似JDBC)。FileSystem有很多实现,HDFS只是其中的一个实现,它的实现类是org.apache.hadoop.hdfs.DistributedFileSystem,它的URI schema为hdfs。Hadoop默认配置的文件系统实现是org.apache.hadoop.fs.LocalFileSystem,URI schema为file,用于管理本地文件。


二、HDFS的基础概念

1、数据块

块设备(例如硬盘)一般会有一个默认块大小,这是设备读写的最小单位,这类设备的块大小一般为几千字节。HDFS同样有块的概念,默认情况下HDFS的块大小为128MB。但是与硬盘的文件系统不一样,当文件小于HDFS的块大小时,不会占用整个块的空间,例如一个1MB大小的文件只占用了1MB的空间,而不是128MB。HDFS的块比硬盘的大是为了最小化寻址开销,如果块足够大,从磁盘传输数据的时间会明显大于定位这个块位置需要的时间,所以传输一个大文件的时间取决于磁盘传输速率。

使用块来管理分布式文件系统有很多好处,例如一个文件可以大于某个物理设备的容量,文件并不需要存储在一个物理设备上。另一个好处是块可以存储在多个节点上,防止某个设备因为故障而丢失数据。

2、namenode和datanode

HDFS集群有两种节点,分别是namenode和datanode。以管理节点——工作节点方式对外提供服务,即client连接namenode,一个namenode节点负责管理多个datanode。

namenode负责管理文件系统的命名空间,它维护文件系统元数据信息,例如目录和文件名称。这些信息以文件的形式永久保存在硬盘上:分别是命令空间镜像文件和编辑日志文件。namenode也记录每个文件的块所在的数据节点信息,但它并不永久保存块的位置,这些信息会在启动的时候根据数据节点的数据重建。

datanode就是文件系统的工作节点。它们根据需要存储数据块信息,并且定期向namenode发送所存储的块列表。HDFS通过把数据块冗余到多个datanode实现数据的安全性,默认副本数量为3。

namenode对外提供服务的时候需要把所有的文件元数据加载到内存,重启的时候会利用镜像文件和编辑日志重建数据,镜像文件类似于Redis的rdb文件。namenode会周期性归档编辑日志来生成一个更加新的镜像文件,由于归档编辑日志的时候namenode也会对外提供服务,这段时间的操作会写入到编辑日志中,所以namenode需要镜像文件和编辑日志一起重建文件元数据。一个大规模的HDFS的恢复是非常消耗时间的(取决于所管理的数据规模),由于namenode是管理节点,没有namenode整个文件系统将无法使用,所以相对datanode,namenode的高可用非常重要。本节主要为对HDFS简单介绍,故先不讨论HDFS的高可用方案。

3、联邦HDFS

由于namenode在内存中维护系统内文件和数据块的关系,很明显namenode运行机器的内存会限制整个集群能存储的文件数量。Hadoop在2.x版本引入的联邦namenode,在联邦环境下,每个namenode管理一个命名空间的一部分。例如一个namenode管理/a目录下的所有文件,另一个namenode管理/b目录下的所有文件。在联邦环境下,每个namenode是独立的,其中一个namenode失效了也不会影响其他namenode。


三、hadoop命令行

Hadoop命令行的fs参数提供了一些方便访问文件系统的操作,所有的参数和格式可以在官网文档FileSystemShell中查询到,这里简单列举一些常用的操作。

-cat:读取文件,并且输出到标准输出

格式:hadoop fs -cat [-ignoreCrc] URI [URI ...]

例如:

  • 打印本地文件系统下的text.txt内容

    hadoop fs -cat file:///D:/test.txt
  • 打印hdfs上根目录下的a.txt内容

    hadoop fs -cat hdfs://192.168.73.130:8082/a.txt

-ls:列出路径下的文件内容

格式:hadoop fs -ls URI

例如:

  • 列出hdfs上根目录的文件内容

    hadoop fs -ls hdfs://192.168.73.130:8082/

输出每一列含义为:权限,副本数,所属用户,所属用户组,文件大小,修改时间,文件名。权限字段由有7个标识位,第一个标识位含义是文件类型,如果是目录则为d,然后紧跟的6个标识位表示所属用户、所属用户组、其他用户的是否可读、可写、可执行,可执行权限可以忽略,因为不能在HDFS中执行。第二列为副本数,目录的元数据保存在namenode上,所以没有副本数。

示例输入如下:

hadoop fs -ls hdfs://192.168.73.130:8082/
Found 2 items
-rw-r--r-- 3 debian supergroup 19481 2023-01-25 15:30 hdfs://192.168.73.130:8082/a.txt
drwxr-xr-x - debian supergroup 0 2023-01-28 09:08 hdfs://192.168.73.130:8082/test

-copyFromLocal:复制本地文件到HDFS

格式:hadoop fs -copyFromLocal localsrc URI

例如:

  • 把本地的文件a.txt复制到HDFS的/testDir/a.txt上

    hadoop fs -copyFromLocal a.txt hdfs://192.168.73.130:8082/testDir/a.txt

-copyToLocal:复制HDFS文件到本地

格式:hadoop fs -copyToLocal URI localsrc

例如:

  • 把HDFS的/testDir/a.txt复制到本地

    hadoop fs -copyToLocal hdfs://localhost:8082/testDir/a.txt a.txt

四、FileSystem常用api

1、文件的读取

使用方法FileSystem#open()可以打开一个FSDataInputStream输入流,然后可以像读取本地文件一样文件中的数据。但是与一般的输入流不一样,FSDataInputStream实现了Seekable和接口PositionedReadable,它们分别支持随机读取和指定位置读取。

Seekable的声明如下:

public interface Seekable {
/**
* 设置下一次读取的时,使用的偏移量
*/
void seek(long pos) throws IOException; /**
* 返回当前读取偏移量
*/
long getPos() throws IOException;
}

getPos返回当前读取偏移量,seek设置下一次read的偏移量,偏移量是当前距离文件起始位置的字节数。例如可以用如下代码重复读取文件开头的2048个字节;

FSDataInputStream in = .....;
byte[] buff = new buff[2048];
in.read(buff);
in.seek(0);
in.read(buff);

seek使用起来很方便,但是是一个相对高开销的操作,需要慎重使用。

PositionedReadable的声明如下:

public interface PositionedReadable {
/**
* 从position指定的位置开始读取length个长度的数据,复制到buffer的offset处,返回实际读取到的字节数
*/
int read(long position, byte[] buffer, int offset, int length)
throws IOException; /**
* 从position指定的位置开始读取length个长度的数据,复制到buffer的offset处
* 如果到达文件结尾抛出EOFException
*/
void readFully(long position, byte[] buffer, int offset, int length) throws IOException; /**
* 从position指定的位置开始读取buffer.length个长度的数据,复制到buffer的offset处
* 如果到达文件结尾抛出EOFException
*/
void readFully(long position, byte[] buffer) throws IOException;
}

read函数把指定偏移量数据读取到buffer中,但是实际读取的字节数需要调用者接受返回值进行判断。readFully效果也类似,但是如果到达文件结尾会抛出EOFException。PositionedReadable所有的方法都不会改变当前流读取文件的位置,同时它的方法也都是线程安全的。

2、文件的写入

传入一个Path对象,然后使用FileSystem#create可以创建一个新文件,并且返回一个FSDataOutputStream对象。与java其他的api不一样,调用create方法会自动创建父级目录。

使用FileSystem#append()可以向一个已存在的文件尾追加内容,需要说明的是这个方法是一个可选的实现,并不是每一个文件系统都正常此方法。

3、目录创建

调用FileSystem#mkdirs()方法可以新建一个目录,通常创建文件不需要显示调用此方法,因为创建文件会自动创建对应的父级目录。

4、文件的删除

调用FileSystem#delete()可以删除一个文件或者目录。

5、文件元数据信息

使用FileSystem#getFileStatus方法可以返回一个FileStatus对象来获取文件或者目录的的状态信息,例如是否为目录、权限、文件长度等数据。

FileSystem#listStatus可以列出目录下所有的文件信息。listStatus有多个重载方法,可以额外传入一个org.apache.hadoop.fs.PathFilter用来过滤目录的文件。

6、HDFS的一致性模型

对于创建一个目录,HDFS可以保证操作是立即可见的。但是对于写入数据并不能保证其可见性。例如对于以下一段Java程序代码:

OutputStream out = ...;
out.write(buff);
out.flush();

如果是操作本地文件,调用flush方法,会把缓冲区数据刷新到硬盘上,保证其可见性。然而对于HDFS,即使调用了flush方法也不能保证可见性,需要等到数据超过一个块之后才能对其他读取进程可见。但是HDFS的实现提供了两个方法用于保证可见性,分别是FSDataOutputStream#hflushFSDataOutputStream#hsynchsync和操作系统的sync方法类似,保证数据已经存储在datanode的硬盘上,而hflush仅仅保证数据写入到datanode的内存。调用close关闭流会自动调用一次hflush


五、demo程序

我使用FileSystem常用api实现了一个客户端demo,代码地址在github 的hdfsApiExample模块,打包此模块可以得到一个hdfs-api-example-1.0-SNAPSHOT.jar的文件,它的使用方法如下:

参数:

  • fs:指定hdfs的namenode地址,假设你有一个namenode地址是hdfs://192.168.73.130:8082
  • u:操作hdfs的用户,根据hdfs配置情况,写入的时候可能需要这个参数
  • o:实际需要执行的命令,分别支持ls(查询目录文件),rm(删除),mkdir(创建目录),cp(复制文件)

示例:

  • 列出hdfs上,根目录的文件

    hadoop jar hdfs-api-example-1.0-SNAPSHOT.jar -fs hdfs://192.168.73.130:8082 -u debian -o ls /
  • 删除hdfs上,/cnblog目录。使用额外的r参数递归删除非空目录

    hadoop jar hdfs-api-example-1.0-SNAPSHOT.jar -fs hdfs://192.168.73.130:8082 -u debian -o rm r /cnblog
  • 在根目录下创建一个cnblog目录

    hadoop jar hdfs-api-example-1.0-SNAPSHOT.jar -fs hdfs://192.168.73.130:8082 -u debian -o mkdir /cnblog
  • 复制本地文件test.txt到hdfs的根目录上

    hadoop jar hdfs-api-example-1.0-SNAPSHOT.jar -fs hdfs://192.168.73.130:8082 -u debian -o cp text.txt hdfs:/test.text
  • 复制hdfs的根目录文件text.txt到本地目录上

    hadoop jar hdfs-api-example-1.0-SNAPSHOT.jar -fs hdfs://192.168.73.130:8082 -u debian -o cp hdfs:/test.text text.txt

04HDFS简介的更多相关文章

  1. ASP.NET Core 1.1 简介

    ASP.NET Core 1.1 于2016年11月16日发布.这个版本包括许多伟大的新功能以及许多错误修复和一般的增强.这个版本包含了多个新的中间件组件.针对Windows的WebListener服 ...

  2. MVVM模式和在WPF中的实现(一)MVVM模式简介

    MVVM模式解析和在WPF中的实现(一) MVVM模式简介 系列目录: MVVM模式解析和在WPF中的实现(一)MVVM模式简介 MVVM模式解析和在WPF中的实现(二)数据绑定 MVVM模式解析和在 ...

  3. Cassandra简介

    在前面的一篇文章<图形数据库Neo4J简介>中,我们介绍了一种非常流行的图形数据库Neo4J的使用方法.而在本文中,我们将对另外一种类型的NoSQL数据库——Cassandra进行简单地介 ...

  4. REST简介

    一说到REST,我想大家的第一反应就是“啊,就是那种前后台通信方式.”但是在要求详细讲述它所提出的各个约束,以及如何开始搭建REST服务时,却很少有人能够清晰地说出它到底是什么,需要遵守什么样的准则. ...

  5. Microservice架构模式简介

    在2014年,Sam Newman,Martin Fowler在ThoughtWorks的一位同事,出版了一本新书<Building Microservices>.该书描述了如何按照Mic ...

  6. const,static,extern 简介

    const,static,extern 简介 一.const与宏的区别: const简介:之前常用的字符串常量,一般是抽成宏,但是苹果不推荐我们抽成宏,推荐我们使用const常量. 执行时刻:宏是预编 ...

  7. HTTPS简介

    一.简单总结 1.HTTPS概念总结 HTTPS 就是对HTTP进行了TLS或SSL加密. 应用层的HTTP协议通过传输层的TCP协议来传输,HTTPS 在 HTTP和 TCP中间加了一层TLS/SS ...

  8. 【Machine Learning】机器学习及其基础概念简介

    机器学习及其基础概念简介 作者:白宁超 2016年12月23日21:24:51 摘要:随着机器学习和深度学习的热潮,各种图书层出不穷.然而多数是基础理论知识介绍,缺乏实现的深入理解.本系列文章是作者结 ...

  9. Cesium简介以及离线部署运行

    Cesium简介 cesium是国外一个基于JavaScript编写的使用WebGL的地图引擎,一款开源3DGIS的js库.cesium支持3D,2D,2.5D形式的地图展示,可以自行绘制图形,高亮区 ...

  10. 1.Hibernate简介

    1.框架简介: 定义:基于java语言开发的一套ORM框架: 优点:a.方便开发;           b.大大减少代码量;           c.性能稍高(不能与数据库高手相比,较一般数据库使用者 ...

随机推荐

  1. 完全背包问题 —— 贪心优化 DP 范围

    题意: 现在有 \(2n+1\) 个物品(\(n\le 300\)),体积分别为 \(-n,-n+1,\dots,-1,0,1,\dots,n\),第 \(i\) 个物品有 \(a_i\) 个,求选出 ...

  2. IDEA中Java项目创建lib目录并生成依赖

    首先介绍说明一下idea在创建普通的Java项目,是没有lib文件夹的,下面我来带大家来创建一下1.右键点击项目,创建一个普通的文件夹 2.取名为lib 3.把项目所需的jar包复制到lib文件夹下 ...

  3. IP分类与子网划分

    1.IP地址的格式  每一类地址都由两个固定长度的字段组成: (1)网络号 net-id:它标志主机(或路由器)所连接到的网络 (2)主机号 host-id:它标志该主机(或路由器).   最大可指派 ...

  4. docker-compose编排启动LNMP

    2-1.docker-compose启动php #生成php镜像  [root@rocky8 data]#vim /data/dockerfile/ubuntu_php/Dockerfile  FRO ...

  5. ISCTF2022WP

    ISCTF2022改名叫套CTF吧(bushi),博主菜鸡一个,套题太多,挑一些题写下wp,勿喷. MISC 可爱的emoji   下载下来是个加密压缩包,根据hint掩码爆破密码 得到密码:KEYI ...

  6. .NET 7.0 重磅发布及资源汇总

    2022-11-8 .NET 7.0 作为微软的开源跨平台开发平台正式发布.微软在公告中表示.NET 7为您的应用程序带来了C# 11 / F# 7,.NET MAUI,ASP.NET Core/Bl ...

  7. SpringBoot 08: SpringBoot综合使用 MyBatis, Dubbo, Redis

    业务背景 Student表 CREATE TABLE `student` ( `id` int(11) NOT NULL AUTO_INCREMENT, `name` varchar(255) COL ...

  8. 2022-11-04 Acwing每日一题

    本系列所有题目均为Acwing课的内容,发表博客既是为了学习总结,加深自己的印象,同时也是为了以后回过头来看时,不会感叹虚度光阴罢了,因此如果出现错误,欢迎大家能够指出错误,我会认真改正的.同时也希望 ...

  9. 基于python的数学建模---非线性规划

    凸函数的非线性规划 minimize 求解的是局部最优解 简单的函数,无所谓 复杂的函数 初始值的设定很重要 scipy.optimize.minimize(fun,x0,args=(),method ...

  10. OSI传输层TCP与UDP协议、应用层简介、socket模块介绍及代码优化、半连接池的概念

    目录 传输层之TCP与UDP协议 应用层 socket模块 socket基本使用 代码优化 半连接池的概念 传输层之TCP与UDP协议 TCP与UDP都是用来规定通信方式的 通信的时候可以随心所欲的聊 ...