Chapter3 分布式文件系统HDFS

news/2024/5/20 0:49:21 标签: hadoop, big data, hdfs, 大数据

3.1分布式文件系统

计算机集群结构:

  • 分布式文件系统把文件分布存储导多个计算机节点上,成千上万的计算机节点构成计算机集群。
  • 与之前使用多个处理器和专业高级硬件的并行化处理装置不同的是,目前的分布式文件系统采用的计算机集群都是由普通硬件构成的,这大大降低了硬件上的开销。
    在这里插入图片描述

分布式文件系统结构:

  • 单机无法处理海量数据,所以要利用计算机集群。
  • 分布式文件系统在物理结构上是由计算机集群中的多个节点构成的,这些节点分为两类。
  • 一类叫做主节点(Master Node)或者名称节点(NameNode)。
  • 一类叫做从节点(Slave Node)或者数据节点(DataNode)。
    在这里插入图片描述

3.2分布式文件系统HDFS简介

HDFS的全称为Hadoop Distributed File System,是Hadoop的两大核心技术之一,解决海量数据的分布式存储问题。

HDFS要实现的目标:

  1. 兼容廉价的硬件设备
    要让企业以可承担的成本存储数据。
  2. 实现流数据读写
    传统文件系统进行数据读写时以块为单位,但HDFS满足海量数据批量处理需求。
  3. 支持大数据
    HDFS文件可以达到TB。
  4. 支持简单的文件模型
    只允许追加,不允许修改。
  5. 强大的跨平台兼容性

HDFS自身的局限性:

  1. 不适合低延迟的数据访问
    HDFS不能满足实时处理需求。
  2. 无法高效存储大量小文件
    HDFS通过源数据指引客户端到哪个节点寻找文件。源数据会保存在HDFS的内存中,要在内存中建立数据索引结构。若小文件过多,数据结构会非常庞大,搜索效率极低。
  3. 不支持多用户写入及任意修改文件
    只允许追加,不允许修改。

3.3HDFS相关概念

3.3.1 块

HDFS中块的概念和普通文件系统存在联系,也存在区别。
联系:都是为了分摊磁盘读写开销,即在大量数据间分摊磁盘寻址的开销
区别:HDFS中的一个块比普通文件系统的块大很多。普通文件系统的块大约为几十字节,而HDFS中一个块默认为64MB。
在这里插入图片描述
HDFS引入"块"的原因:
1.支持面向大规模数据存储:
一个文件的大小不会受到单个节点的存储容量的限制,可以远大于网络中任意节点的存储容量。
2. 降低分布式节点的寻址开销:
访问HDFS文件时要经过三级寻址,从源数据目录找到数据节点,再从数据节点中取出数据。若块过小会导致寻址开销很大。

设计"块"时要注意:如果块过大会导致MapReduce只有一两个任务在执行,完全牺牲了MapReduce的并行度,不能发挥分布式并行处理的效果。

HDFS引入"块"的好处:

  1. 支持大规模数据存储:
    文件以块为单位进行存储,一个大规模文件可以被拆分成若干个文件块,不同文件块可以被分发到不同的节点上。因此,一个文件的大小不会受到单个节点的存储容量的限制,可以远大于网络中任意节点的存储容量。
  2. 简化系统设计:
    块的大小是固定的,可以计算出一个节点可以存储多少文件块。
  3. 适合数据备份:
    每个文件块都可以冗余存储到多个节点上,提高了系统的容错性和可用性。
3.3.2 名称节点和数据节点

名称节点(NameNode)是主节点,负责存储元数据(保存在内存中),相当于是数据目录。比如一个很大的文件要被切分成很多块,这些块被分布存储到不同的机器上,名称节点需要记录源数据的存储情况。即它需要保存文件、“块”、以及DateNode之间的映射关系。
数据节点(DateNode)负责存储实际数据,即文件内容(保存在磁盘中)。维护"块"到本地文件的映射关系。
在这里插入图片描述

元数据中包含的内容:
在这里插入图片描述
名称节点(NameNode)负责管理分布式文件系统的命名空间(NameSpace),保存着两个核心的数据结构(FsImage和EditLog):
FsImage存储的元数据包括:文件的复制等级、修改和访问时间、访问权限、块大小以及组成文件的块。
在这里插入图片描述

需要注意的是,在FsImage中,没有具体记录块在哪个数据节点中存储。 是名称节点把这些映射信息保存在内存中,当数据节点加入HDFS集群时,数据节点会把自己所包含的块列表告知给名称节点,此后会定期执行这种告知操作,以确保名称节点的块映射是最新的。
在这里插入图片描述
名称节点的启动过程:
1.名称节点启时,会将FsImage文件的内容从底层磁盘加载到内存中,将其与EditLog中的各项操作进行合并,使得内存中的元数据和实际同步,从而得到最新的元数据。
2.一旦二者合并成功后,得到新的文件,名称节点会将最新的FsImage文件保存下来,并删除之前的版本。并创建一个空的EditLog。
3.随着数据的不断增加,新的更新操作都会写到EditLog中。(不直接更新FsImage文件的原因是它的规模太大了,更新起来很困难,会导致系统速度变慢。而EditLog的规模很小。)
在这里插入图片描述
使用这种方式记录更新操作,会带来一个新的问题:在名称节点运行期间,EditLog的规模将不断增大,一旦规模达到一定程度又会影响系统运行速度。
解决方案:使用第二名称节点(Secondary NameNode)
第二名称节点:可以作为名称节点的冷备份(防止名称节点发生故障),也可以帮助解决EditLog不断增大的问题。一般单独运行在一台机器上。
第二名称节点的工作机制:
在这里插入图片描述
第二名称节点(Secondary NameNode)的工作流程:
1.Secondary NameNode会定期的与NameNode进行通信,并在某个阶段请求名称节点停止写入EditLog文件,暂时将新的写操作写入一个新的文件edit.new中。
2.Secondary NameNode通过HTTP的GET方式,从NameNode中获取FsImage和EditLog文件拷贝到本地。
3.Secondary NameNode将拷贝的FsImage载入到内存,并一条条执行EditLog中的各项更新。即将两个文件进行合并,合并之后FsImage文件应为最新。
4.合并之后,再通过post方式将FsImage文件发送给NameNode。
5.NameNode用收到的新FsImage文件替换之前的旧版,并将edits.new更改为EditLog。
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
数据节点(DataNode):负责具体数据的存储和读取,根据客户端或名称节点的调度进行数据的存储和检索,并且向名称节点定期发送自己存储块的列表。
每个数据节点中的数据会被保存到各自节点的本地Linux文件系统中。

3.4HDFS体系结构

3.4.1 概述

HDFS采用主从架构。在一个HDFS集群中,主节点(NameNode)起到目录结构作用,其他节点(DataNode)都负责具体数据的存储。
结构图如下所示:
在这里插入图片描述
客户端访问数据时,首先从NameNode处获取元数据信息,得知要访问数据的存储位置,然后客户端访问各个机器,获取数据。
客户端存储数据时,首先询问NameNode文件的写入方式,NameNode会将文件划成不同块、存储块的数据节点,客户端将相关块分布存储到相关的数据节点即可。

3.4.2 HDFS命名空间

HDFS命名空间只有一个,包含目录、文件、块。

HDFS使用了传统的分级文件体系,因此可以像访问普通文件系统一样,访问HDFS。

3.4.3 通信协议

所有的HDFS通信协议都构建在TCP/IP协议基础之上。

客户端通过一个可配置端口向名称节点主动发起TCP连接,使用客户端协议与名称节点交互。

名称节点和数据节点之间使用数据节点协议进行交互。

客户端通过远程调用(RPC)和数据节点进行交互。注意,名称节点不会主动发起远程调用,只响应来自客户端和数据节点的远程调用请求。

在这里插入图片描述

3.4.4 客户端

HDFS客户端是一个库,暴露HDFS文件系统接口,隐藏后台实现的复杂性。

可以通过客户端支持打开、读取、写入等常见操作。

操作可以通过Java API方式实现,也可以通过Shell命令的方式实现。

注意,严格来说,客户端不算是HDFS的一部分。

3.4.5 局限性

HDFS体系结构存在的局限性包括以下几点:

  1. 命名空间限制
    名称节点是保存在内存中的。因此,名称节点能够容纳的对象(文件、块)的个数会受到空间大小限制。
  2. 性能的瓶颈
    整个分布式文件的吞吐量,受限于单个名称节点的吞吐量。(客户端访问数据都需要请求NameNode)
  3. 隔离问题
    由于集群中只有一个名称节点,只有一个命名空间。因此无法对不同的应用程序进行隔离。
  4. 集群的可用性
    一旦唯一的名称节点发生故障,会导致整个集群都变得不可用。
    注意,在HDFS1.0中,第二名称节点不能解决这个问题,因为第二名称节点是冷备份机制,名称节点发生故障时,必须停止一段时间进行恢复,才能提供对外服务。此时整个集群仍不可用。但是在HDFS2.0中,解决了这个问题。在2.0中设置了两个进行分区管理,还设置了热备份。

3.5HDFS存储原理

3.5.1 冗余数据保存的问题

由于HDFS架构在廉价的机器上,会不断的出现故障,因此必须有冗余数据保存。

在HDFS中,每一个数据以块为单位进行冗余保存。通常一个数据块的多个副本会被分不到不同数据节点上,通常冗余因子为3(一个块被默认保存3份),冗余因子可以修改。

如果配置的是伪分布式,把名称节点和数据节点放在了同一台机器上,此时冗余因子只能是1,因为只有一台机器。

这种多副本保存的好处:

  1. 加快数据传输速度
    当客户端A、B、C同时访问数据块1时,三个客户端可以在三个机器上并行操作。
  2. 很容易检查数据错误
    副本都是一样的,可以通过对照检查错误。
  3. 保证数据可靠性
    即使一个副本损坏,还有副本是可用的。并且在HDFS设计中,一旦系统探测到某个副本发生故障,会自动复制生成新的副本,让副本保持在冗余因子数量的水平。
3.5.2 数据保存策略问题

(1)数据存放
图中共有两个机架,每个机架都存放着三个数据节点。在这里插入图片描述当一个块到达时,首先复制块的副本。
第一个副本:放在上传文件的数据节点。如果提交数据请求不是来自集群内部的节点,就随机挑选一台磁盘不太满、CPU不太忙的节点,用于放置第一个副本。
第二个副本:放在和第一个副本不同的机架上。
第三个副本:放在和第一个副本相同机架的其他节点上。
更多副本:随机放置。

(2)数据读取
基本原则:就近读取。

HDFS提供了一个API,可以确定一个数据节点所属机架的ID,客户端也可以调用API获取自己所属的机架ID。

客户端读取数据时,从名称节点获取数据块不同副本的存放位置列表,列表中包含了副本所在的数据节点,可以调用API来确定客户端和这些数据节点所属的机架ID。当发现某个数据块副本对应的机架ID和客户端对应的机架ID相同时,就优先选择该副本读取数据。如果没有发现,就随机选择一个副本读取数据。

3.5.3 数据恢复的问题

HDFS集群中有很多节点,会出现错误,常见错误包括以下三种情形:
(1)名称节点出错
名称节点只有一个,且保存着最核心的两个数据结构(FsImage和EditLog),如果这两个数据结构出错,整个HDFS都将失效。
因此,HDFS设置了备份机制,将两个核心文件同步复制到备份服务器SecondaryNameNode上。当NameNode出现问题后,会根据SecondaryNameNode中的FsImage和EditLog进行修复。
在这里插入图片描述

(2)数据节点出错
数据节点(DateNode)在运行期间,会定期向名称节点发送"心跳信息",报告自己的状态。

一旦名称节点经过一段时间没有收到数据节点发送的信息,就知道数据节点发生故障了。

如果名称节点探测到某个数据节点不可用,会将数据节点标记为"宕机",并调整冗余数据的位置,将数据块进行迁移。

HDFS和其他分布式文件系统的最大区别就是可以调整冗余数据的位置。
在这里插入图片描述

(3)数据本身出错
使用"校验码"机制探测数据是否出现了问题。客户端读取数据后,对数据进行校验码校验,确认数据是否正确。

在文件被创建时,客户端会对每一个文件块进行信息摘录,并把这些信息写入到同一个路径的隐藏文件里面。

客户端读取文件时,会先读取该信息文件。然后利用该信息文件对每个读取的数据块进行检验。如果检验到出现错误,客户端就请求另外一个数据节点读取该文件块,并向名称节点报告这个文件块错误。名称节点会定期检查并重新复制这个文件块。

3.6HDFS数据读写

在Hadoop中,设置了通用文件系统的抽象基类FileSystem,这个抽象基类可以被分布式文件系统继承。所有可能使用Hadoop文件系统的代码,都要使用这个类。

DistributedFileSystem是FileSystem在HDFS文件系统中的具体实现。

FileSystem的open()方法返回一个输入流FSDataInputStream对象,在HDFS系统中,具体的输入流就是DFSInputStream。create()方法返回一个输出流FSDataOutputStream对象,在HDFS系统中,具体的输出流就是DFSOutputStream。

在这里插入图片描述

3.6.1 读数据的过程

读取一个文件的代码如下:在这里插入图片描述
HDFS读数据的过程如下:

  1. 打开文件:
    由HDFS客户端发起读请求。用FileSystem声明文件系统类,实例化对象fs。抽象基类是FileSystem,根据conf生成子类DistributedFileSystem,即此时生成的fs与HDFS相关,是DistributedFileSystem类的一个对象,但由于HDFS隐藏了复杂的底层实现过程,所以用户在变编程时看到的就是FileSystem。
FileSystem fs = FileSystem.get(conf);
想要读取相关数据,还需要创建输入流。其中uri是文件的地址。
FSDataInputStream is = fs.open(new Path(uri))
  1. 获取数据块信息
    open()方法返回一个输入流FSDataInputStream对象,在HDFS系统中,具体的输入流就是DFSInputStream。
    DFSInputStream通过远程调用和名称节点进行沟通,通过ClientProtocal.getBlockLocations()查找下一个数据块,询问要读取的数据被保存在那些节点上。名称节点会根据位置距离信息进行排序,并把包含的文件的开始部分的数据块位置信息返回。

  2. 读取请求
    之前名称节点已经返回了数据块位置信息列表,客户端获得输入流后,可以调用read()函数,选择距离客户端最近的数据节点建立连接、读取数据。

  3. 读取数据
    将数据从数据节点读取到客户端后,FSDataInputStream就要关闭和这个数据节点的连接。

  4. 获取数据块信息
    由于文件可能很大,关闭和上一个数据节点的连接后,仍有数据没读完。
    此时需要再次询问名称节点,通过ClientProtocal.getBlockLocations()查找下一个数据块。名称节点再次返回根据距离远近排序的数据块位置信息列表。

  5. 读取数据
    输入流获得数据块位置信息列表后,继续通过read()函数和节点建立连接、读取数据,读取完毕后再关闭连接。
    重复上述5~6过程,直到所有数据块读写完成。

  6. 关闭文件
    所有数据块读写完成后,调用close()方法关闭文件即可。至此读过程结束。

整体流程图:
在这里插入图片描述

3.6.2 写数据的过程

写入一个文件的代码如下:
在这里插入图片描述

HDFS写数据的过程如下:

  1. 创建文件请求
    用FileSystem声明文件系统类,实例化对象fs。
FileSystem fs = FileSystem.get(conf);
接着创建输出流。
FSDataOutputStream os = fs.create(new Path(uri))
  1. 创建文件元数据
    create()方法返回一个输出流FSDataOutputStream对象,在HDFS系统中,具体的输出流就是DFSOutputStream。
    由于文件有很多数据块,因此要询问名称节点,将数据块写到哪些数据节点。
    DFSOutputStream执行远程调用,让名称节点在文件系统的命名空间中新建一个文件。名称节点检查文件是否存在、客户端是否有权限创建文件,检查通过后名称节点会创建文件并返回。

  2. 写入数据
    HDFS中有一种高效的写数据方式,称为流水线复制。
    将整个数据分成一个个分包,将这些分包分别放入到DFSOutputStream对象的内部队列。DFSOutputStream会向名称节点申请保持这些数据块的数据节点。

  3. 写入数据包
    DFSOutputStream向名称节点申请后,名称节点会返回要写入的数据节点的信息列表。
    这些数据节点会形成数据流管道,会将一个个分包重新打包成数据包,发送到整个数据流管道的第一个数据节点,第一个数据节点再发给第二个节点,第二个节点再向下一个节点发送。
    这是因为这些相同的副本要重复写到这些数据块上,用于备份。

  4. 接收确认包
    数据写入后,需要给出确认信息。
    但是确认包并非是由数据节点直接发送给客户端,而是以接力的方式。从数据流管道最末端的数据节点依次向前发送确认信息,直至到达客户端。

  5. 关闭文件
    调用close()方法关闭文件即可。

整体流程图:
在这里插入图片描述


http://www.niftyadmin.cn/n/1799911.html

相关文章

USACO 2.4

The Tamworth Two 两只塔姆沃斯牛 还以为又是一道 大搜索 想不到是大水.... 直接模拟 搞个多维数组判重 Overfencing穿越栅栏 先两遍floyd ... 然后 把 每个点到出口的最短距离统计出来 , 再取最大... Bessie Come Home回家 spfa 秒过.. Fractions to Decimals分…

Chapter4 分布式数据库HBase

4.1概述 4.1.1从BigTable说起 HBase是BigTable的开源实现。 BigTable是一个分布式存储系统,它最初是用于解决谷歌公司内部的大规模网页所搜问题。 网页搜索可以分为两个阶段: 1.第一阶段:建立整个网页的索引。 通过爬虫不断的抓取各个网站…

网站DDOS***防护实战老男孩经验心得分享

网站DDOS***防护实战老男孩经验心得分享 老男孩由于要培训学生、批改作业,因此最近比较忙,还要经常写书、录视频,搞的思路混乱,受朋友邀请参加某论坛活动,推迟不过,挤了一点时间,给大家简单分…

Chapter5 MapReduce

5.1概述 5.1.1分布式并行编程 MapReduce是一种分布式并行编程框架。 在计算机发展史上的"摩尔定律":CPU的性能每隔18个月就可以翻一番。然而,从2005年起,摩尔定律逐渐失效,因为CPU制作工艺存在上限、性能不可能无限提…

su和sudo命令

摘要: 超级用户是系统最高权限的拥有者,是系统管理唯一的胜任者;由于权限的超级并且达到无所不能的地步,如果管理不擅,必会对系统安全造成威胁。 除了尽可能的避免用直接用超级用户root登录系统外,我们还要…

Chapter6 数据仓库Hive

6.1数据仓库概念 6.1.1什么是数据仓库 数据仓库:数据仓库是一个面向主题的、集成的、相对稳定的、反映历史变化的数据集合,用于支持管理决策。 数据仓库的目的:支持企业内部的商业分析和决策,让企业可以基于数据仓库的分析结果…

sgu 114

2019独角兽企业重金招聘Python工程师标准>>> 带权中位数的应用。 给定位置数组x[0...n]和权重数组w[0...n] 求 x 使得 w0|x0 - x| w1|x1 - x| ... wn|xn - x|最小 #include <cstdio> #include <vector> #include <cmath> #include <cassert…

Hive初始化元数据仓库:java.sql.SQLException : Access denied for user ‘hive‘@‘localhost‘ (using password: YES)

使用命令./bin/schematool -dbType mysql -initSchema初始化元数据仓库时&#xff0c;出现如下错误&#xff1a; 导致报错的原因可能并不相同&#xff0c;这里只写出我遇到的情况&#xff08;Linux下&#xff09;&#xff0c;有两种解决方法&#xff1a; 方法一&#xff1a;检…