Ⅰ HDFS数据的读写过程(重点)
(1)客户端通过FileSystem.open()打开文件,相应地,在HDFS文件系统中DistributedFileSystem具体实现了FileSystem。因此,调用了open()方法后,DistributedFileSystem会创建输入流FSDataInputStream,对于HDFS而言,具体的输入流就是DFSInputStream.
(2)DFSInputStream的构造函数中,输入流通过ClientProtocal.getBloackLocations()远程调用NameNode,获得文件开始部分数据块的保存位置。对于该数据块。名称节点返回保存该数据块的锁哟数据节点的地址,同时根据距离客户端的远近对数据节点进行排序,然后DistributedFileSystem会利用DFSInputStream来实例化FSDataInputStream返回给客户端,同时返回了数据块的数据节点的地址。
(3)获得输入流FSDataInputStream后,客户端调用read()函数开始读取数据。输入流根据前面的排序结果,选择距离客户端最近的数据节点建立连接,然后读取数据。
(4)读取完毕后,关闭流,如果还有下一个数据块,就与下一个DN建立连接,读取数据块。
(1)客户端发起创建文件请求
(2)DistributedFileSystem通过RPC远程调用名称节点,在文件系统的命名空间中创建一个新的文件。名称节点会执行一些检查,比如这个文件是否存在,客户端是否有权限等。通过检查,名称节点会狗仔一个新文件,并且添加文件信息。然后返回给客户端一个输出流,客户端通过这个输出流,用它来写入数据。
(3)获得输出流FSDataOutputStream以后,客户端调用输出流的write方法想HDFS中对应的文件写入数据
客户端向输出流FSDataOutputStream中写入的数据会首先被分成一个个的分包,这些分包被放入DFSOutputStream对象的内部队列。每个包64K,包中有数据块,块是512字节,这些包被放入DFSOutputStream对象的内部队列,FSDataOutputStream向名称节点申请保存文件和副本数据块的若干数据节点。这些数据节点形成一个数据流管道,队列中的分包最后被打包成数据包,发往数据流管道第一个节点,第一个节点又复制到第二、三个节点,采用流水线复制策略(在写入磁盘时候 是每次4k往磁盘写)
(5)为保证所有数据节点的数据准备DataNode返回确认包 Client收到应答,将对应分宝从内部队列移除。开始下一个分包。
Ⅱ 大量较为频繁读写的文件一般如何进行存储
如果数据量不是很大(G级别以下),文拿笑件不是特别零碎,可以直接存在硬盘上。
但是如果数据量已经/衡敏败可能超过T级别,或者文件小且零碎,建议还是放在HDFS等分布式文件系统上。
我存储爬虫的html以及图片数据,是通过HDFS的MapFile格式存储的。MapFile是个已排序的键值对文件格式,我的键采用的是url的hash+采集时间,值就是文件内容。并且封装了原生的MapFile.Reader实现了读取和一定程度的缓存(目前只用了LRU)。
在HDFS提倡一次写入,多次读取的前提下,文件的更新只能是通过失效旧,使用新的策略。即把旧的元数据标记为失效,插入新的元数据,并把更新的文件写入HDFS。读取是通过新的元数据定位到文件。同时,要定期的清除已失效的文件,即把未失效的元数据读出来,将对应的文件写到新的MapFile,删除旧的MapFile,即可实现物理删除。
当然还可以使用HBase。HBase是面向列的,二进制存储的,可横向拓展的NoSQL。可以咐颤把不大于64M的数据作为单元格数据直接写进去。但是有一定的学习成本,而且对集群的硬件要求比较高。
Ⅲ Hadoop系列之HDFS架构
本篇文章翻译了Hadoop系列下的 HDFS Architecture ,原文最初经过笔者翻译后大概有6000字,之后笔者对内容进行了精简化压缩,从而使笔者自己和其他读者们阅读本文时能够更加高效快速的完成对Hadoop的学习或复习。本文主要介绍了Hadoop的整体架构,包括但不限于节点概念、命名空间、数据容错机制、数据管理方式、简单的脚本命令和垃圾回收概念。
PS:笔者新手一枚,如乱棚老果看出哪里存在问题,欢迎下方留言!
Hadoop Distributed File System(HDFS)是高容错、高吞吐量、用于处理海量数据的分布式文件系统。
HDFS一般由成百上千的机器组成,每个机器存储整个数据集的一部分数据,机器故障的快速发现与恢复是HDFS的核心目标。
HDFS对接口的核心目标是高吞吐量而非低延迟。
HDFS支持海量数据集合,一个集群一般能够支持千万以上数量级的文件。
HDFS应用需要对文件写一次读多次的接口模型,文件变更只支持尾部添加和截断。
HDFS的海量数据与一致性接口特点,使得迁移计算以适应文件内容要比迁移数据从而支持计算更加高效。
HDFS支持跨平台使用。
HDFS使用主从架构。一个HDFS集群由一个NameNode、一个主服务器(用于管理系统命名空间和控制客户端文件接口)、大量的DataNode(一般一个节点一个,用于管理该节点数据存储)。HDFS对外暴露了文件系统命名空间并允许在文件中存储用户数据。一个文件被分成一个或多个块,这些块存储在一组DataNode中。NameNode执行文件系统命名空间的打开关闭重命名等命令并记录着块和DataNode之间的映射。DataNode用于处理客户端的读写请求和块的相关操作。NameNode和DataNode一般运行在GNU/Linux操作系统上,HDFS使用Java语言开发的,因此NameNode和DataNode可以运行在任何支持Java的机器上,再加上Java语言的高度可移植性,使得HDFS可以发布在各种各样的机器上。一个HDFS集和亩群中运行一个NameNode,其他机器每个运行一个(也可以多个,非常少见)DataNode。NameNode简化了系统的架构,只用于存储所有HDFS元数据,用户数据不会进入该节点。下图为HDFS架构图:
HDFS支持传统的分层文件管理,用户或者应用能够在目录下创建目录或者文件。文件系统命名空间和其他文件系统是相似的,支持创建、删除、移动和重命名文件。HDFS支持用户数量限制和访问权限控制,不支持软硬链接,用户可以自己实现软硬链接。NameNode控制该命名空间,命名空间任何变动几乎都要记录到NameNode中。应用可以在HDFS中对文件声明复制次数,这个次数叫做复制系数,会被记录到NameNode中。
HDFS将每个文件存储为一个或多个块,并为文件设置了块的大小和复制系数从而支持文件容错。一个文件所有的块(除了最后一个块)大小相同,后来支持了可变长度的块。复制系数在创建文件时赋值,后续可以更改。文件在任何时候只能有一个writer。NameNode负责块复制,它周期性收到每个数据节点的心跳和块报告,心跳表示数据节点的正常运作,块报告包含了这个DataNode的所有块。
副本存储方案对于HDFS的稳定性和性能至关重哗升要。为了提升数据可靠性、灵活性和充分利用网络带宽,HDFS引入了机架感知的副本存储策略,该策略只是副本存储策略的第一步,为后续优化打下基础。大型HDFS集群一般运行于横跨许多支架的计算机集群中,一般情况下同一支架中两个节点数据传输快于不同支架。一种简单的方法是将副本存放在单独的机架上,从而防止丢失数据并提高带宽,但是增加了数据写入的负担。一般情况下,复制系数是3,HDFS存储策略是将第一份副本存储到本地机器或者同一机架下一个随机DataNode,另外两份副本存储到同一个远程机架的不同DataNode。NameNode不允许同一DataNode存储相同副本多次。在机架感知的策略基础上,后续支持了 存储类型和机架感知相结合的策略 ,简单来说就是在机架感知基础上判断DataNode是否支持该类型的文件,不支持则寻找下一个。
HDFS读取数据使用就近原则,首先寻找相同机架上是否存在副本,其次本地数据中心,最后远程数据中心。
启动时,NameNode进入安全模式,该模式下不会发生数据块复制,NameNode接收来自DataNode的心跳和块报告,每个块都有一个最小副本数量n,数据块在NameNode接受到该块n次后,认为这个数据块完成安全复制。当完成安全复制的数据块比例达到一个可配的百分比值并再过30s后,NameNode退出安全模式,最后判断是否仍然存在未达到最小复制次数的数据块,并对这些块进行复制操作。
NameNode使用名为EditLog的事务日志持续记录文件系统元数据的每一次改动(如创建文件、改变复制系数),使用名为FsImage的文件存储全部的文件系统命名空间(包括块到文件的映射关系和文件系统的相关属性),EditLog和FsImage都存储在NameNode本地文件系统中。NameNode在内存中保存着元数据和块映射的快照,当NameNode启动后或者某个配置项达到阈值时,会从磁盘中读取EditLog和FsImage,通过EditLog新的记录更新内存中的FsImage,再讲新版本的FsImage刷新到磁盘中,然后截断EditLog中已经处理的记录,这个过程就是一个检查点。检查点的目的是确保文件系统通过在内存中使用元数据的快照从而持续的观察元数据的变更并将快照信息存储到磁盘FsImage中。检查点通过下面两个配置参数出发,时间周期(dfs.namenode.checkpoint.period)和文件系统事务数量(dfs.namenode.checkpoint.txns),二者同时配置时,满足任意一个条件就会触发检查点。
所有的HDFS网络协议都是基于TCP/IP的,客户端建立一个到NameNode机器的可配置的TCP端口,用于二者之间的交互。DataNode使用DataNode协议和NameNode交互,RPC包装了客户端协议和DataNode协议,通过设计,NameNode不会发起RPC,只负责响应来自客户端或者DataNode的RPC请求。
HDFS的核心目标是即使在失败或者错误情况下依然能够保证数据可靠性,三种常见失败情况包括NameNode故障、DataNode故障和network partitions。
网络分区可能会导致部分DataNode市区和NameNode的连接,NameNode通过心跳包判断并将失去连接的DataNode标记为挂掉状态,于是所有注册到挂掉DataNode的数据都不可用了,可能会导致部分数据块的复制数量低于了原本配置的复制系数。NameNode不断地追踪哪些需要复制的块并在必要时候进行复制,触发条件包含多种情况:DataNode不可用、复制乱码、硬件磁盘故障或者认为增大负值系数。为了避免DataNode的状态不稳定导致的复制风暴,标记DataNode挂掉的超时时间设置比较长(默认10min),用户可以设置更短的时间间隔来标记DataNode为陈旧状态从而避免在对读写性能要求高的请求上使用这些陈旧节点。
HDFS架构兼容数据各种重新平衡方案,一种方案可以在某个DataNode的空闲空间小于某个阈值时将数据移动到另一个DataNode上;在某个特殊文件突然有高的读取需求时,一种方式是积极创建额外副本并且平衡集群中的其他数据。这些类型的平衡方案暂时还未实现(不太清楚现有方案是什么...)。
存储设备、网络或者软件的问题都可能导致从DataNode获取的数据发生乱码,HDFS客户端实现了对文件内容的校验,客户端在创建文件时,会计算文件中每个块的校验值并存储到命名空间,当客户端取回数据后会使用校验值对每个块进行校验,如果存在问题,客户端就会去另一个DataNode获取这个块的副本。
FsImage和EditLog是HDFS的核心数据结构,他们的错误会导致整个HDFS挂掉,因此,NameNode应该支持时刻维持FsImage和EditLog的多分复制文件,它们的任何改变所有文件应该同步更新。另一个选择是使用 shared storage on NFS 或者 distributed edit log 支持多个NameNode,官方推荐 distributed edit log 。
快照能够存储某一特殊时刻的数据副本,从而支持HDFS在发生错误时会滚到上一个稳定版本。
HDFS的应用场景是大的数据集下,且数据只需要写一次但是要读取一到多次并且支持流速读取数据。一般情况下一个块大小为128MB,因此一个文件被切割成128MB的大块,且每个快可能分布在不同的DataNode。
当客户端在复制系数是3的条件下写数据时,NameNode通过目标选择算法收到副本要写入的DataNode的集合,第1个DataNode开始一部分一部分的获取数据,把每个部分存储到本地并转发给第2个DataNode,第2个DataNode同样的把每个部分存储到本地并转发给第3个DataNode,第3个DataNode将数据存储到本地,这就是管道复制。
HDFS提供了多种访问方式,比如 FileSystem Java API 、 C language wrapper for this Java API 和 REST API ,而且还支持浏览器直接浏览。通过使用 NFS gateway ,客户端可以在本地文件系统上安装HDFS。
HDFS使用目录和文件的方式管理数据,并提供了叫做 FS shell 的命令行接口,下面有一些简单的命令:
DFSAdmin命令集合用于管理HDFS集群,这些命令只有集群管理员可以使用,下面有一些简单的命令:
正常的HDFS安装都会配置一个web服务,通过可配的TCP端口对外暴露命名空间,从而使得用户可以通过web浏览器查看文件内容。
如果垃圾回收配置打开,通过FS shell移除的文件不会立刻删除,而是会移动到一个垃圾文件专用的目录(/user/<username>/.Trash),类似回收站,只要文件还存在于那个目录下,则随时可以被回复。绝大多数最近删除的文件都被移动到了垃圾目录(/user/<username>/.Trash/Current),并且HDFS每个一段时间在这个目录下创建一个检查点用于删除已经过期的旧的检查点,详情见 expunge command of FS shell 。在垃圾目录中的文件过期后,NameNode会删除这个文件,文件删除会引起这个文件的所有块的空间空闲,需要注意的是在文件被删除之后和HDFS的可用空间变多之间会有一些时间延迟(个人认为是垃圾回收机制占用的时间)。下面是一些简单的理解删除文件的例子:
当文件复制系数减小时,NameNode会选择多余的需要删除的副本,在收到心跳包时将删除信息发送给DataNode。和上面一样,这个删除操作也是需要一些时间后,才能在集群上展现空闲空间的增加。
HDFS Architecture
Ⅳ HDFS存储类型与策略
存储类型表示数据节点支持的多种物理存储介质的类型,有如下几类:
* RAM_DISK(transient)
* SSD
* DISK(default)
* ARCHIVE
前三个分别对应内存存储,固态硬盘存储,机械磁盘存储,第4个我认为是压缩格式的困贺机械存储
按照RAM_DISK->SSD->DISK->ARCHIVE的顺序,存取速度由快到慢,单bit存储成本由高到低。
通过datanode角色的配置项dfs.datanode.data.dir可以配置存储介质的位置和类型,比如:
在上表中,前两列分别是策略编号和策略名;第三列表示在有n个副本的情况下,各个副本都会被存放在什么类型的存储上;第四列表示在创建文件(写入第一个副本)时第三列指定的存储无法满足要求时备选的存储类型;第五列表示在生成副本时第三列指定的存储无法满足要求时备选的存储类型。以One_SSD策略为例,正常情况一个副本放在有SSD标签的存储上,其他副本放在DISK标签的存汪御派储上,在正常情况无法得到满足的情况下,副本可能会被“强制”放在SSD或者DISK上。
按照All_SSD->One_SSD->Hot->Warm->Cold的顺序,面向的数据“越来越冷”,可以根据数据的冷热程度选择合理的策略。Lazy_Persist比较特殊,如果一个文件的存储拆弯策略被指定为Lazy_Persist,在写入时会先写入内存,再异步地写入磁盘,官方文档中提到“Applications can choose to use Lazy Persist Writes to trade off some rability guarantees in favor of reced latency.”,即主要用来降低小数据量的写入延迟,代价是在某些情况下会有数据丢失。
Ⅳ HDFS架构
HDFS中的文件是以数据块(Block)的形式存储的,默认最基本的存储单位是128 MB(Hadoop 1.x为64 MB)的数据块。也就是说,存储在HDFS中的文件都会被分割成128 MB一块的数据块进行存储,如果文件本身小于一个数据块的大小,则按实际大竖岁答小存储,并不占用整个数据块空间。HDFS的数据块之所以会设置这么大,其目的是减少寻址开销。数据块数量越多,寻址数据块所耗的时间就越多。当然也不会设置过大,MapRece中的Map任务通常一次只处理一个块中的数据,如果任务数太少,作业的运行速度就会比较慢。HDFS的每一个数据块默认都有三个副本,分别存储在不同的DataNode上,以实现容错功能。因此,若数据块的某个副本丢失并不会影响对数据块的访问。数据块大小和副本数量可在配置文件中更改
NameNode是HDFS中存储元数据(文件名称、大小和位置等信息)的地方,它将所有文件和文件夹的元数据保存在一个文件系统目录树中,任何元数据信息的改变,NameNode都会记录。HDFS中的每个文件都被拆分为多个数据块存放,这种文件与数据块的对应关系也存储在文件系统目录树中,由NameNode维护。NameNode还存储数据块到DataNode的映射信息,这种映射信息包括:数据块存放在哪些DataNode上、每个DataNode上保存了哪些数据块。NameNode也会周期性地接收来自集群中DataNode的“心跳”和“块报告”。通过“心跳”与DataNode保持通信,监控DataNode的状态(活着还是宕机),若长时间接收不到“心跳”信息,NameNode会认为DataNode已经宕机,从而做出相应的调整策略。“块报告”包含了DataNode上所有数据块的列表信息。
DataNode是HDFS中真正存储数据的地方。客户端可以向DataNode请求写入或读取数据块,DataNode还在来自NameNode的指令下执行块的创建、删除和复制,并且周期性地向NameNode汇报数据块信息。
NodeSecondaryNameNode用于帮助NameNode管理元数据,从而使NameNode能够快速、高效地工作。它并不是第二个NameNode,仅是NameNode的一个辅助工具。HDFS的元数据信息主要存储于两个文件中:fsimage和edits。fsimage是文件系统映射文件,主余慧要存储文件元数据信息,其中包含文件系统所有目录、文件信息以及数据块的索引;edits是HDFS操作日志文件,HDFS对文件系统的修改日志会存储到该文件中。当NameNode启动时,会从文件fsimage中读取HDFS的状态,雀辩也会对文件fsimage和edits进行合并,得到完整的元数据信息,随后会将新HDFS状态写入fsimage。但是在繁忙的集群中,edits文件会随着时间的推移变得非常大,这就导致NameNode下一次启动的时间会非常长。为了解决这个问题,则产生了SecondaryNameNode,SecondaryNameNode会定期协助NameNode合并fsimage和edits文件,并使edits文件的大小保持在一定的限制内。SecondaryNameNode通常与NameNode在不同的计算机上运行,因为它的内存需求与NameNode相同,这样可以减轻NameNode所在计算机的压力。
Ⅵ hadoop面试题之HDFS
1、简单介绍下hadoop吧?
广义上hadoop是指与hadoop相关的大数据生态圈。包含hive、spark、hbase等。
狭义上hadoop指的是apache的开源框架。有三个核心组件:
----hdfs:分布式文件存储系统
----yarn:分布式资源管理调度平台
----mr:分布式计算引擎
2、介绍下hdfs?
全称为Hadoop Distributed File System。有三个核心组件:
namenode:有三个作用,第一是负责保存集群的元数据信息,第二是负责维护整个集群节点的正常运行。
第三是负责处理客户端的请求。
datanode:负责实际保存数据。实际执行数据块的读写操作。
secondarynamenode:辅助namenode进行元数据的管理。不是namenode的备份。
3、namenode的工作机制?
namenode在内存中保存着整个内存系统的名称空间和文件数据块的地址映射。整个hdfs可存储的文件数受限于namenode的内存大小。所以hdfs不适合大量小文件的存储。
---namenode有三种元数据存储方式来管理元数据:
》内存元数据:内存中保存了完整的元数据
》保存在磁盘上的元数据镜像文件(fsimage):该文件时hdfs存在磁盘中的元数据检查点,里面保存的是最后一次检查点之前的hdfs文件系统中所有目录和文件的序列化信息。
》数据操作日志文件(edits):用于衔接内存meta data和持久化元数据镜像fsimage之间的操作日志文件。保存了自最后一次检查点之后所有针对hdfs文件系统的操作。如对文件的增删改查。
4、如何查看元数据信息?
因为edits和fsimage文件是经过序列化的,所以不能直接查看。hadoop2.0以上提供了查看两种文件的工具。
----命令:hdfs oiv 可以将fsimage文件转换成其他格式,如xml和文本文件。-i 表示输入fsimage文件。-o 输出文件路径,-p 指定输出文件
hdfs oev可以查看edits文件。同理需要指定相关参数。
详情查看: https://www.imooc.com/article/79705
4、datanode的工作机制?
1)以数据块的形式存储hdfs文件
2)datanode响应客户端的读写请求
3)周期性的向namenode汇报心跳信息、数据块信息、缓存数据块信息
5、secondary namenode工作机制?
当发生checkpoint机制时会触发second namenode进行工作。checkpoint:
新的edists文件不会立即和fsimage文件合并,是在edits文件大小超过(默认)64m,或者时间超过(默认)1小时,会触发checkpoint操作。当checkpoint时,namenode会新建一个edits.new的文件,此时second namenode将文件fsimage文件和edits文件(http get)到本地,然后加载到内存中进行合并,完成的文件名称为fsimage.ckpt。最后 second namenode将该文件(http post)到namenode,然后edits.new和fsimage.ckpt文件转换为fsimage和edits。
6、hdfs的文件副本机制?
所有的文件都是以块的形式保存到hdfs中。块的大小默认为128m。在hdfs-site文件中进行指定。
动态副本创建策略:默认副本数是3,可以在上传文件时,显式设定replication。也可以通过指令修改文件的副本数 hadoop fs -setrep -R 1
7、为实现高可用,hdfs采用了哪些策略?
副本机制、机架感知、心跳机制、安全模式、校验和、回收站、元数据保护、快照机制(具体介绍导航- https://www.jianshu.com/writer#/notebooks/44567747/notes/66453316 )
8、hdfs的存储过程?
①client向hdfs发起写请求,通过RPC与namenode建立通讯。namenode检查文件是否存在等信息,返回是否可以存储。
②client将文件切割为一个个block块,client申请存储第一块block。namenode返回可以存储这个block块的datanode的地址,假设为ABC。
③A到B到C逐级构建pipeline。client向A上传第一个packet,默认为64k。A收到一个packet后会将packet传给B,再传给C。pipeline反方向返回ack信息。最终由第一个节点A将pipelineack发送给client
④一个block完成之后,再进行下一个block的存储过程。
9、hdfs的读过程?
10、hdfs的垃圾桶机制?
hdfs的垃圾桶机制默认是关闭的,需要手动开启。hdfs删除的文件不会立刻就删除,而是在设定的时间后进行删除。
11、hdfs的扩容和缩容
【
12、
Ⅶ Hadoop文档(2.9.2) - HDFS架构
Hadoop分布式文件系统(HDFS)是一种运行在通用硬件上的分布式文件系统。它与传统的分布式文件系统有很多相似之处,但是也有显着的不同。HDFS是高容错的,可以部署在低成本硬件上。HDFS提供了对应用数据的高吞吐量访问,适用于具有盯败大数据集的应用。HDFS为了流数据访问放松了一些POSIX的限制。
HDFS是主从结构。一个HDFS集群由一个NameNode和一组DataNode组成。NameNode是主服务器,负责管理文件系统命名空间汪则首以及客户端对文件的访问。DataNode通常每个节点一个,负责管理存储。HDFS对外暴露了一个文件系统命名空间并允许用户数据作为文件存储。在内部实现上,一个文件会被分割成一个或多个block,这些block存储在一组DataNode上。NameNode负责执行文件系统命名空间操作,例如打开,关闭,重命名文件和目录等。此外NameNode还维护着block和DataNode之间的映射关系。DataNode负责处理来自客户端的读写请求,并根据NameNode的指令创建,删除,备份block。
NameNode和DataNode都是运行在通用机器上的软件。这些机器通常使用Linux系统。HDFS使用Java构建,任何支持Java的机器都可以运行NameNode和DataNode。一种典型的集群部署方式是使用一台机器运行NameNode,其它机器每台运行一个DataNode实例。
HDFS使用传统的分层文件结构。用户可以创建目录并在目录下存储文件。文件系统命名空间结构与传统文件系统类似,用户可以创建,删除文件,将文件从一个目录移动到另一个目录,重命名文件。HDFS支持用户限额和访问权限。
NameNode维护整个文件系统命名空间,它会记录任何对命名空间的修改。应用程序可以指定HDFS中文件的备份数量。文件的拷贝数称为该文件的备份因子。这个信息也存储在NameNode中。
HDFS可以跨机器存储海量文件。每个文件分成一个block的序列存储。为了容错,文件的block会被备份。每个文件的block大小和备份因子都是可配置的。
文件中所有block的大小是相等的(除了最后一个),而对append和hsync提供可变长block支持后,用户可以直接创建一个新block,不必继续填充最后一个block。
应用程序可以指定文件的备份数。备份因子可在文件创建时指定,也可以稍后修改。HDFS的文件都是一次写入的(除了append和truncate),并且任何时候都只有一个写入器。
NameNode决定如何备份block。它周期性的接收来自DataNode的心跳检测和block报表。收到心跳检测说明DataNode工作正常,block报表包含该DataNode上的所有block。
备份文件的位置对HDFS的可用性和性能至关重要。对备份的优化让HDFS从众多分布式系统中脱颖而出。这个工作需要大量的优化和经验。机架感知备份放置策略的目的是提高数据的可靠性,可用性和网络带宽利用率。目前的备份放置策略实现是这个方向上的第一步。短期目标是在生产环境上对其进行验证,更多的了解它的行为,为测试和研究更复杂的策略奠定基础。
大型HDFS集群的机器通常隶属于多个机架。两个不同机架上的节点进行通信必须通过交换机。一般来说,同一机架机器之间的网络带宽要优于不同机架机器间的网络带宽。
NameNode通过Hadoop Rack Awareness进程确定每个DataNode所属的机架ID。一个简单但是并困数非最优的策略是将备份放置在独立的机架上。这种策略可以避免机架故障时丢失数据,读数据时也可以利用多个机架的网络带宽。这种策略在集群中平均分配备份文件,这样组件发生故障时可以平衡负载。但是这种策略会增加写入成本,因为数据需要跨机架传输。
最常见的情况,备份因子是3。HDFS的放置策略是:如果写入器位于DataNode上,则将副本放置在本地计算机,否则随机选择一个DataNode,另一个副本放置在另一个远程机架的节点上,最后一个副本放在同一个远程机架的另一个节点上。这种策略减少了机架间的写入流量,从而提高写性能。机架发生故障的几率远小于节点故障几率。这种策略并不影响数据可靠性和可用性,但是它确实减少了读操作时的聚合网络带宽,因为一个block被放置到两个机架上而不是三个。这种策略的文件副本并不是均匀的分布在所有机架上,副本的三分之一位于一个节点,剩下的三分之二位于另一个机架上。这种策略可以提高写性能,而不会影响数据可靠性和读性能。
如果备份因子大于3,那么第四个和之后的副本随机放置,同时要保证副本数量不能超过机架的上限(公式: (replicas - 1) / racks + 2 )。
由于DataNode不能放置同一个block的多个副本,所以最大备份因子就是最大DataNode数。
在提供了存储类型和存储策略的支持之后,除了机架感知,NameNode放置副本时也会考虑放置策略。NameNode首先根据机架感知选择节点,然后根据备份文件的放置策略检查该节点的存储类型,如果该候选节点没有要求的存储类型,NameNode会查找下一个节点。如果第一轮没有找到足够的节点放置备份,NameNode会使用后备存储类型开始第二轮查找。
目前,副本放置策略依然在开发中。
为了减少带宽消耗和读延迟,HDFS会尝试找寻一个离读请求最近的副本。如果读请求节点所在机架有这样一个副本,HDFS就优先使用这个副本。如果HDFS集群跨越多个数据中心,则本地数据中心的副本优先于远程副本。
启动HDFS时,NameNode会进入一种称为安全模式的特殊状态。安全模式下数据block无法备份。NameNode会从DataNode接收心跳检测和block报表。block报表包含该DataNode下所有数据block的列表信息。每个block都有一个指定的最小备份数。只有block的最小备份数登记到NameNode中后,block才可以备份。备份登记结束后,NameNode退出安全模式。这是如果还有block不满足最小备份数的条件,NameNode才开始备份这些block。
HDFS命名空间由NameNode保存,NameNode使用一个称为EditLog的事务日志记录对文件系统元数据的所有更改。例如,创建一个新文件会在EditLog中插入一条对应记录,同样的,修改文件备份因子也会插入一条记录。NameNode使用本地文件存储EditLog。整个文件系统命名空间,包括文件与block之间的映射关系,文件系统数据等,都保存在FsImage文件中。
NameNode在内存中维护文件系统命名空间和文件block映射关系的镜像。当NameNode启动,或者某个阈值触发了检查点时,NameNode从磁盘上读取FsImage和EditLog的内容,将所有EditLog中的事务操作应用到FsImage的内存镜像中,然后在磁盘上生成一个全新的FsImage。之后可以截断EditLog,因为所有事务都已持久化到FsImage。这个过程称为检查点。检查点的目的是通过获取文件系统元数据的快照并保存到FsImage来保证HDFS文件系统元数据的一致性。读取FsImage可能很快,但是持续编辑FsImage就不同了。因此我们将操作记录到EditLog中,而不是直接修改FsImage。在检查点期间,所有EditLog操作应用到FsImage。检查点可以按周期触发( dfs.namenode.checkpoint.period ),也可以按事务数触发( dfs.namenode.checkpoint.txns )。如果两个属性都设置了,第一个满足的阈值会触发检查点。
DataNode在本地文件系统中存储HDFS数据。DataNode对HDFS文件一无所知,它以block为单位存储HDFS数据。DataNode不会在同一个目录下保存所有文件。相反,它使用启发式方法来确定每个目录的最佳文件数,并适时创建子目录。在同一个目录下创建所有文件并不是最佳选择,因为本地文件系统可能无法支持一个目录下的大量文件。DataNode启动时,它会扫描整个本地文件系统,生成一个本地文件与数据block之间的关系列表,将其发送给NameNode,这个列表称为block报告。
所有HDFS通信协议都构建在TCP/IP协议之上。客户端通过TCP端口与NameNode建立连接,它使用ClientProtocol与NameNode交互。DataNode使用DataProtocol与NameNode交互。一个RPC抽象封装了客户端协议和DataNode协议。NameNode从不初始化任何RPC,它只是响应来自的客户端和DataNode的请求。
HDFS的主要目标是即使出现故障也可以可靠的存储数据。三种常见的故障分别是:NameNode故障,DataNode故障和网络分区。
DataNode周期性的发送心跳检测给NameNode。网络分区可能导致某些DataNode无法连接NameNode。NameNode无法收到DataNode的心跳检测后,它会把这样的DataNode标记为dead,并不在发送新的I/O请求。注册到死亡DataNode上的数据对HDFS来说不再可用,也会导致某些block的备份数少于文件指定的最小备份数。NameNode持续追踪block的备份情况并在必要时初始化备份操作。重备份的原因是多种多样的:DataNode不可用,某个备份文件损坏,DataNode磁盘故障,或者文件的备份因子增大。
为了避免DataNode状态抖动引起的备份风暴,标记DataNode死亡的超时时间设置的很长(默认超过10分钟)。用户可以设置一个更短的时间将DataNode标记为陈旧(stale),这样可以避免对性能敏感的工作负载的陈旧DataNode的读写操作。
HDFS架构与数据重平衡scheme兼容。scheme可以在DataNode的磁盘空间低于某个阈值时将数据移动到另一个DataNode上。如果对某个文件的需求特别高,scheme还可以动态创建额外的副本并平衡到整个集群中。这些数据平衡scheme还未实现。
从DataNode中读取的block可能是损坏的。损坏的原因有多种:磁盘故障,网络故障,或者软件问题。HDFS客户端会对文件内容进行校验和检查。当客户端创建一个HDFS文件时,它会计算出文件所有block的校验和并保存在同一个命名空间的一个独立的隐藏文件中。当客户单检索文件时还要检查对应校验和文件中的值。如果校验和不匹配,客户端会尝试该block其它节点上的副本。
FsImage和EditLog是HDFS的核心数据结构。如果它们发生损坏,HDFS就无法使用了。因此,可以通过配置让NameNode维护多个FsImage和EditLog的拷贝。对两个文件的修改会同步到所有拷贝中。这种同步操作会降低NameNode的TPS,但是这种牺牲是可接受的,因为HDFS是数据密集,不是元数据密集。NameNode重启时,它会选择最一致的FsImage和EditLog使用。
另一种减低故障的办法是使用HA。
(略)
HDFS的目的是支持大型文件。HDFS支持一次写入多次读取。一个典型的block大小是128MB。因此,HDFS文件按照128MB的大小分割,每个block可能分布在不同的节点上。
客户端向HDFS文件写入数据时,如果备份因子是三,NameNode使用备份目标选择算法检索出一组DataNode。这个列表是可以存储副本的DataNode。客户端先向第一个DataNode写入数据,DataNode接收数据并将数据传输到列表中的第二个DataNode。第二个DataNode开始接收数据并继续传输数据到第三个DataNode。这样,数据通过管道从一个DataNode传输到下一个。
(略)
如果开启了trash配置,从FS shell中删除的文件并不会立刻从HDFS中删除,HDFS将它移动到一个trash目录(每个用户都有自己的trash目录, /user/<username>/.Trash )。只要文件还在trash目录中就可以快速恢复。
最近删除的文件移动到 /user/<username>/.Trash/Current 目录中,每隔一段时间,HDFS会为这些文件创建检查点文件( /user/<username>/.Trash/<date> )并删除旧检查点文件。
如果trash中的文件过期了,NameNode将这些文件从命名空间中删除。与文件关联的block被释放。删除文件和空间释放之间可能会有延迟。
下面是一个例子,首先创建两个文件:
然后删除test1,该文件会被移到Trash目录:
接着跳过Trash删除test2:
现在可以查看Trash目录:
文件的备份因子降低后,NameNode选择可以删除的副本,在下次心跳检测时把信息发送给DataNode,之后DataNode删除block并释放空间。