HDFS设计思想和相关概念(hdfs的设计要实现哪些目标)
wxin55 2024-11-11 14:42 21 浏览 0 评论
一、HDFS简介
1、简单介绍
HDFS(Hadoop Distributed FileSystem),是Hadoop项目的两大核心之一,源自于Google于2003年10月发表的GFS论文,是对GFS的开源实现。HDFS在最开始是作为Apache Nutch搜索引擎项目的基础架构而开发的。
HDFS在设计之初,就是要运行在通用硬件(commodity hardware)上,即廉价的大型服务器集群上,因此,在设计上就把硬件故障作为一种常态来考虑,可以保证在部分硬件发生故障的情况下,仍然能够保证文件系统的整体可用性和可靠性。
HDFS有一下特点:
- HDFS是一个高度容错性的系统,适合部署在廉价的机器上的分布式文件系统。
- HDFS能提供高吞吐量的数据访问,非常适合大规模数据集上的应用。
- HDFS放宽了一部分POSIX约束,来实现流式读取文件系统数据的目的。
- HDFS也是一个易于扩展的分布式文件系统
2、HDFS设计目标
a、大规模数据集
HDFS用来处理很大的数据集。HDFS上的文件,大小一般都在GB至TB。因此同时,HDFS应该能提供整体较高的数据传输带宽,能在一个集群里扩展到数百个节点。一个单一的HDFS实例应该能支撑千万计的文件。目前在实际应用中,HDFS已经能用来存储管理PB级的数据了。
b、硬件错误
我们应该知道,硬件组件发生故障是常态,而非异常情况。HDFS可能由成百上千的服务器组成,每一个服务器都是廉价通用的普通硬件,任何一个组件都有可能一直失效,因此错误检测和快速、自动恢复是HDFS的核心架构目标,同时能够通过自身持续的状态监控快速检测冗余并恢复失效的组件。
c、流式数据访问
流式数据,特点就是,像流水一样,不是一次过来而是一点一点“流”过来,而处理流式数据也是一点一点处理。
HDFS的设计要求是:能够高速率、大批量的处理数据,更多地响应"一次写入、多次读取"这样的任务。在HDFS上一个数据集,会被复制分发到不同的存储节点中。而各式各样的分析任务多数情况下,都会涉及数据集中的大部分数据。为了提高数据的吞吐量,Hadoop放宽了POSIX的约束,使用流式访问来进行高效的分析工作
d、简化一致性模型
HDFS应用需要一个“一次写入多次读取”的文件访问模型。一个文件经过创建、写入和关闭之后就不需要改变了。这一假设简化了数据一致性问题,并且使高吞吐量的数据访问成为可能。MapReduce应用或网络爬虫应用都非常适合这个模型。目前还有计划在将来扩充这个模型,使之支持文件的附加写操作。
e、移动计算代价比移动数据代价低
一个应用请求的计算,离它操作的数据越近就越高效,这在数据达到海量级别的时候更是如此。将计算移动到数据附近,比之将数据移动到应用所在之处显然更好,HDFS提供给应用这样的接口。
f、可移植性
HDFS在设计时就考虑到平台的可移植性,这种特性方便了HDFS作为大规模数据应用平台的推广。
3、HDFS的优缺点
通过上述的介绍,我们可以发现HDFS的优点是:
- a、高容错性:数据自动保存多个副本,副本丢失后,会自动恢复。
- b、适合批处理:移动计算而非数据、数据位置需要暴露给计算框架。
- c、适合大数据处理:GB、TB、甚至PB级数据、百万规模以上的文件数量,1000以上节点规模。
- d、流式文件访问:一次性写入,多次读取;保证数据一致性。
- e、可构建在廉价机器上:通过多副本提高可靠性,提供了容错和恢复机制。
而HDFS同样有自己的缺点:
1)不适合低延迟数据访问
HDFS的设计目标有一点是:处理大型数据集,高吞吐率。这势必要以高延迟为代价的。因此HDFS不适合处理一些用户要求时间比较短的低延迟应用请求。
2)不适合小文件存取
一是因此存取大量小文件需要消耗大量的寻地时间(比如拷贝大量小文件与拷贝同等大小的一个大文件) 。
二是因为namenode把元信息存储在内存中,一个节点的内存是有限的。一个block元信息的内存消耗大约是150 byte。而存储1亿个block和1亿个小文件都会消耗掉namenode 20GB内存,哪个适合?当然是1亿个block(大文件)更省内存。
3)不适合并发写入、文件随机修改
HDFS上的文件只能有一个写者,也仅仅支持append操作,不支持多用户对同一文件的写操作,以及在文件任意位置进行修改。
二、HDFS设计思想
现在想象一下这种情况:有四个文件 0.5TB的file1,1.2TB的file2,50GB的file3,100GB的file4;有7个服务器,每个服务器上有10个1TB的硬盘。
在存储方式上,我们可以将这四个文件存储在同一个服务器上(当然大于1TB的文件需要切分),我们需要使用一个文件来记录这种存储的映射关系吧。用户是可以通过这种映射关系来找到节点硬盘相应的文件的。那么缺点也就暴露了出来:
第一、负载不均衡。因为文件大小不一致,势必会导致有的节点磁盘的利用率高,有的节点磁盘利用率低。
第二、网络瓶颈问题。一个过大的文件存储在一个节点磁盘上,当有并行处理时,每个线程都需要从这个节点磁盘上读取这个文件的内容,那么就会出现网络瓶颈,不利于分布式的数据处理。
我们来看看HDFS的设计思想:以下图为例,来进行解释。
HDFS将50G的文件file3切成多个Block(存储块),每一个Block的大小都是固定的,比如128MB,它把这多个数据块以多副本的行式存储在各个节点上 ,再使用一个文件把哪个块存储在哪些节点上的映射关系存储起来。有了这样的映射关系,用户读取文件的时候就会很容易读取到。每个节点上都有这样的Block数据,它会分开网络瓶颈,利于分布式计算,解决了上面的第二个问题。因为每个块的大小是一样的,所以很容易实现负载均衡,解决了上面的第一个问题。
三、HDFS相关概念
1、块(Block)概念
在我们熟知的Windows、Linux等系统上,文件系统会将磁盘空间划分为每512字节一组,我们称之为"磁盘块",它是文件系统读写操作的最小单位。而文件系统的数据块(Block)一般是磁盘块的整数倍,即每次读写的数据量必须是磁盘块的整数倍。
在传统的文件系统中,为了提高磁盘的读写效率,一般以数据块为单位,而不是以字节为单位,比如机械硬盘包含了磁头和转动部件,在读取数据时有一个寻道的过程,通国转动盘片和移动磁头的位置,来找到数据在机械硬盘中的存储位置,然后才能进行读写。在I/O开销中,机械硬盘的寻址时间时最耗时的部分,一旦找到第一条记录,剩下的顺序读取效率是非常高的,因此以块为单位读写数据,可以把磁盘寻道时间分摊到大量数据中。
HDFS同样引入了块(Block)的概念,块是HDFS系统当中的最小存储单位,在hadoop2.0中默认大小为128MB。在HDFS上的文件会被拆分成多个块,每个块作为独立的单元进行存储。多个块存放在不同的DataNode上,整个过程中 HDFS系统会保证一个块存储在一个数据节点上 。但值得注意的是 如果某文件大小或者文件的最后一个块没有到达128M,则不会占据整个块空间 。
当然块大小可以在配置文件中hdfs-default.xml中进行修改(此值可以修改)
<property>
<name>dfs.blocksize</name>
<value>134217728</value>
<description>默认块大小,以字节为单位。可以使用以下后缀(不区分大小写):k,m,g,t,p,e以重新指定大小(例如128k, 512m, 1g等)</description>
</property>
<property>
<name>dfs.namenode.fs-limits.min-block-size</name>
<value>1048576</value>
<description>以字节为单位的最小块大小,由Namenode在创建时强制执行时间。这可以防止意外创建带有小块的文件可以降级的大小(以及许多块)的性能。</description>
</property>
<property>
<name>dfs.namenode.fs-limits.max-blocks-per-file</name>
<value>1048576</value>
<description>每个文件的最大块数,由写入时的Namenode执行。这可以防止创建会降低性能的超大文件</description>
</property>
HDFS中的NameNode会记录文件的各个块都存放在哪个dataNode上,这些信息一般也称为元信息(MetaInfo) 。元信息的存储位置一般由dfs.namenode.name.dir来指定。
<property>
<name>dfs.namenode.name.dir</name>
<value>file://${hadoop.tmp.dir}/dfs/name</value>
</property>
而datanode是真实存储文件块的节点,块在datanode的位置一般由dfs.datanode.data.dir来指定。
<property>
<name>dfs.datanode.data.dir</name>
<value>file://${hadoop.tmp.dir}/dfs/data</value>
</property>
HDFS上的块为什么远远大与传统文件系统,是有原因的。目的是为了最小化寻址开销时间。
HDFS寻址开销不仅包括磁盘寻道开销,还包括数据库的定位开销,当客户端需要访问一个文件时,首先从名称节点获取组成这个文件的数据块的位置列表,然后根据位置列表获取实际存储各个数据块的数据节点的位置,最后,数据节点根据数据块信息在本地Linux文件系统中找到对应的文件,并把数据返回给客户端,设计一个比较大的块,可以把寻址开销分摊到较多的数据中,相对降低了单位数据的寻址开销
举个例子: 块大小为128MB,默认传输效率100M/s ,寻址时间为10ms,那么寻址时间只占传输时间的1%左右
当然,块也不能太大,因为另一个核心技术MapReduce的map任务一次只处理一个数据块,如果任务太少,势必会降低工作的并行处理速度。
HDFS的块概念,在解决了大数据集文件的存储同时,不仅解决了文件存取的网络瓶颈问题,还
- 解决了大数据集文件的存储:大文件分块存储在多个数据节点上,不必受限于单个节点的存储容量。
- 简化系统设计:块大小固定,单个节点的块数量比较少,容易管理。元数据可以单独由其他系统负责管理。
- 适合数据备份:每个块可以很容易的冗余存储到多个节点上,提高了系统的容错性和可用性
2、Namenode和Datanode
HDFS集群上有两类节点,一类是管理节点(Namenode),一类是工作节点(Datanode)。而HDFS就是以管理节点-工作节点的模式运行的,在HDFS上,通常有一个Namenode和多个Datanode(一个管理者master,多个工作者slave)。
作为master的NameNode负责管理分布式文件系统的命名空间(NameSpace),即维护的是文件系统树及树内的文件和目录。这些信息以 两个核心文件(fsImage和editlog)的形式持久化在本地磁盘中。
fsImage命名空间镜像文件,用于维护文件系统树以及文件树中所有文件和目录的元数据;操作日志文件editlog中记录了所有针对文件的创建、删除、重命名等操作。namenode也记录了每个文件的各个块所在的datanode的位置信息,但并不持久化存储这些信息,而是在系统每次启动时扫描所datanode重构得到这些信息,也就是说保存在运行内存中。
Namenode在启动时,会将FsImage的内容加载到内存当中,然后执行EditLog文件中的各项操作,使得内存中的元数据保持最新。这个操作完成以后,就会创建一个新的FsImage文件和一个空的EditLog文件。名称节点启动成功并进入正常运行状态以后,HDFS中的更新操作都被写到EditLog,而不是直接写入FsImage,这是因为对于分布式文件系统而言,FsImage文件通常都很庞大,如果所有的更新操作都直接往FsImage文件中添加,那么系统就会变得非常缓慢。相对而言,EditLog通常都要远远小于FsImage,更新操作写入到EditLog是非常高效的。名称节点在启动的过程中处于“安全模式”,只能对外提供读操作,无法提供写操作。在启动结束后,系统就会退出安全模式,进入正常运行状态,对外提供写操作。
作为slave的Datanode是分布式文件系统HDFS的工作节点,负责数据块的存储和读取(会根据客户端或者Namenode的调度来进行数据的存储和检索),并且定期向Namenode发送自己所存储的块的列表。每个Datanode中的数据会被保存在本地Linux文件系统中。
3、SecondaryNamenode
在Namenode运行期间,HDFS会不断发生更新操作,这些更新操作不会直接写到fsimage文件中,而是直接被写入到editlog文件的,文件会越来越大。当Namenode重启时,会加载fsimage加载到内存中,并且逐条执行editlog中的记录,editlog文件大,就会导致整个过程变得非常缓慢,使得Namenode在启动过程中长期处于“安全模式”,无法正常对外提供写操作,影响了用户的使用。
HDFS采用了SecondaryNameNode这个守护线程,可以定期完成editlog与fsImage的合并操作,减小editlog文件大小,缩短Namenode重启时间;也可以作为Namenode的一个“检查点”,将保存Namenode内存中的元数据信息,保存在fsimage镜像文件中。
相关推荐
- ES6中 Promise的使用场景?(es6promise用法例子)
-
一、介绍Promise,译为承诺,是异步编程的一种解决方案,比传统的解决方案(回调函数)更加合理和更加强大在以往我们如果处理多层异步操作,我们往往会像下面那样编写我们的代码doSomething(f...
- JavaScript 对 Promise 并发的处理方法
-
Promise对象代表一个未来的值,它有三种状态:pending待定,这是Promise的初始状态,它可能成功,也可能失败,前途未卜fulfilled已完成,这是一种成功的状态,此时可以获取...
- Promise的九大方法(promise的实例方法)
-
1、promise.resolv静态方法Promise.resolve(value)可以认为是newPromise方法的语法糖,比如Promise.resolve(42)可以认为是以下代码的语...
- 360前端一面~面试题解析(360前端开发面试题)
-
1.组件库按需加载怎么做的,具体打包配了什么-按需加载实现:借助打包工具(如Webpack的require.context或ES模块动态导入),在使用组件时才引入对应的代码。例如在V...
- 前端面试-Promise 的 finally 怎么实现的?如何在工作中使用?
-
Promise的finally方法是一个非常有用的工具,它无论Promise是成功(fulfilled)还是失败(rejected)都会执行,且不改变Promise的最终结果。它的实现原...
- 最简单手写Promise,30行代码理解Promise核心原理和发布订阅模式
-
看了全网手写Promise的,大部分对于新手还是比较难理解的,其中几个比较难的点:状态还未改变时通过发布订阅模式去收集事件实例化的时候通过调用构造函数里传出来的方法去修改类里面的状态,这个叫Re...
- 前端分享-Promise可以中途取消啦(promise可以取消吗)
-
传统Promise就像一台需要手动组装的设备,每次使用都要重新接线。而Promise.withResolvers的出现,相当于给开发者发了一个智能遥控器,可以随时随地控制异步操作。它解决了三大...
- 手写 Promise(手写输入法 中文)
-
前言都2020年了,Promise大家肯定都在用了,但是估计很多人对其原理还是一知半解,今天就让我们一起实现一个符合PromiseA+规范的Promise。附PromiseA+规范地址...
- 什么是 Promise.allSettled()!新手老手都要会?
-
Promise.allSettled()方法返回一个在所有给定的promise都已经fulfilled或rejected后的promise,并带有一个对象数组,每个对象表示对应的pr...
- 前端面试-关于Promise解析与高频面试题示范
-
Promise是啥,直接上图:Promise就是处理异步函数的API,它可以包裹一个异步函数,在异步函数完成时抛出完成状态,让代码结束远古时无限回掉的窘境。配合async/await语法糖,可...
- 宇宙厂:为什么前端离不开 Promise.withResolvers() ?
-
大家好,很高兴又见面了,我是"高级前端进阶",由我带着大家一起关注前端前沿、深入前端底层技术,大家一起进步,也欢迎大家关注、点赞、收藏、转发。1.为什么需要Promise.with...
- Promise 新增了一个超实用的 API!
-
在JavaScript的世界里,Promise一直是处理异步操作的神器。而现在,随着ES2025的发布,Promise又迎来了一个超实用的新成员——Promise.try()!这个新方法简...
- 一次搞懂 Promise 异步处理(promise 异步顺序执行)
-
PromisePromise就像这个词的表面意识一样,表示一种承诺、许诺,会在后面给出一个结果,成功或者失败。现在已经成为了主流的异步编程的操作方式,写进了标准里面。状态Promise有且仅有...
- Promise 核心机制详解(promise机制的实现原理)
-
一、Promise的核心状态机Promise本质上是一个状态机,其行为由内部状态严格管控。每个Promise实例在创建时处于Pending(等待)状态,此时异步操作尚未完成。当异步操作成功...
- javascript——Promise(js实现promise)
-
1.PromiseES6开始支持,Promise对象用于一个异步操作的最终完成(包括成功和失败)及结果值的表示。简单说就是处理异步请求的。之所以叫Promise,就是我承诺,如果成功则怎么处理,失败怎...
你 发表评论:
欢迎- 一周热门
- 最近发表
-
- ES6中 Promise的使用场景?(es6promise用法例子)
- JavaScript 对 Promise 并发的处理方法
- Promise的九大方法(promise的实例方法)
- 360前端一面~面试题解析(360前端开发面试题)
- 前端面试-Promise 的 finally 怎么实现的?如何在工作中使用?
- 最简单手写Promise,30行代码理解Promise核心原理和发布订阅模式
- 前端分享-Promise可以中途取消啦(promise可以取消吗)
- 手写 Promise(手写输入法 中文)
- 什么是 Promise.allSettled()!新手老手都要会?
- 前端面试-关于Promise解析与高频面试题示范
- 标签列表
-
- hive行转列函数 (63)
- sourcemap文件是什么 (54)
- display none 隐藏后怎么显示 (56)
- 共享锁和排他锁的区别 (51)
- httpservletrequest 获取参数 (64)
- jstl包 (64)
- qsharedmemory (50)
- watch computed (53)
- java中switch (68)
- date.now (55)
- git-bash (56)
- 盒子垂直居中 (68)
- npm是什么命令 (62)
- python中+=代表什么 (70)
- fsimage (51)
- nginx break (61)
- mysql分区表的优缺点 (53)
- centos7切换到图形界面 (55)
- 前端深拷贝 (62)
- kmp模式匹配算法 (57)
- jsjson字符串转json对象 (53)
- jdbc connection (61)
- javascript字符串转换为数字 (54)
- mybatis 使用 (73)
- 安装mysql数据库 (55)