HDFS 面试知识点
一、HDFS 基础知识
##### 概述
为什么HDFS能存储海量数据 概念 :hdfs是一个分布式的文件系统,用于海量数据的存储 设计思想:分而治之,将大文件、大批量文件,分布式存放在大量服务器上,采取分而治之的方式对海量数据进行运算分析 作用:为各类分布式运算框架,如:MR,Spark ,等提供数据存储服务(hbase、hive也是依托于hdfs进行数据存储) 特性:HDFS中的文件在物理上是分块存储(block),块的大小可以通过配置参数( dfs.blocksize)来规定,默认大小在hadoop2.x版本中是128M,老版本中是64M
1、HDFS 的优点:
a.兼容廉价的硬件设备,即hdfs可以构建在廉价的服务器上面,通过多副本提高可靠性 b.适合处理大数据(1)数据规模:能够处理的数据规模达到了GB、TB甚至是PB 级别(2)文件规模:能够处理百万规模以上的文件数量,文件数量数量相当大 c.简单的文件模型,即hdfs 采用“一次写入,多次读取,且不支持文件的修改”的简单的文件模型 d.高容错性(1)数据自动保存多个副本,通过增加副本形式,提高容错性(2)一个副本丢失以后,可以进行自动恢复
2、HDFS 的缺点:
a.不适合低延迟数据访问。HDFS 是面向大规模数据批处理而设计的,因此具有很高的数据吞吐率。但是同时这也意味着具有较高的延迟。对于低延迟的应用程序而言,HBase 是一个更好的选择。 b.无法高效存储大量小文件。这里的小文件是指文件大小小于一个块的大小。原因在于:HDFS采用名称节点来管理文件系统的元数据,这些元数据是被保存在内存中的,从而使客户端可以快速地获取的文件实际的存储位置。如果存在大量的小文件存在以下问题:(1)首先,需要花费较多的时间用于获取文件的实际存储位置(2)其次,名称节点保存元数据的所需要的内存空间也会大大的增大(3)再次,用MR处理大量小文件时,会产生大量的map任务,大大增加了线程管理的开销(4)最后,访问大量小文件的速度要远远低于访问几个大文件的速度 c.不支持多用户写入以及任意修改。HDFS只允许一个文件只有一个写入者,不允许存在多个用户对同一文件执行写操作。而且只允许对文件执行追加操作,不能执行随机写操作。
3、数据块
在传统的文件系统中,为了提高磁盘读写效率,一般是以数据块为单位来进行读写而非字节。HDFS同样也采用数据块的概念,默认大小为128M。HDFS中的文件会被拆分成多个块,每一个块作为独立的单元进行存储。 一、 HDFS数据块与普通文件系统的文件块的不同点:1、HDFS 数据块要比不同文件系统的数据块大得多。原因在于,为了最小化寻址时间。HDFS的寻址开销不仅包括磁盘的寻道时间,还包括数据块的定位时间。当客户端需要访问一个文件时,首先需要从名称节点获取组成该文件的所有数据块的位置列表;然后根据位置列表获取存储数据块的数据节点的位置;最后数据节点根据数据块的信息在本地Linux文件系统找到对应的文件,并将数据返回给客户端。设计一个较大的块,可以把上述寻址时间分摊到较多的数据上,降低单位数据的寻址开销。2、同时在分布式文件系统中,如果一个文件大小小于一个数块的大小,它并不占用整个数据块的存储空间。(即当一个1MB的文件存储在一个128MB的块中时,文件只使用1MB的磁盘空间,而不是128MB)二、设置数据块的好处:1、支持大规模数据存储。一个大规模文件可以被拆分为若干个文件块,不同的文件块可以被分发到不同的节点存储。因此一个文件大小不在受限于单节点存储。2、使用抽象块概念而非整个文件作为存储单元,大大简化存储系统的设计。3、适合数据备份。每个文件块都可以冗余存储到多个节点上,大大提高了系统的容错性和可靠性。三、为什么块的大小不能设置的太小,也不能设置的太大1、HDFS数据块设置的太小,相同大小的文件需要读取的数据块的数量就会增加,从而增加了寻址时间。因为程序一直在找块开始的位置。2、HDFS数据块设置的太大,从磁盘中传输数据的时间会明显大于数据块的定位时间,导致程序处理的时间也会很长。同时MR 中一个map 任务只能处理一个数据块的数据,如果数据块设置的太大,map的任务就会变少,从而降低了作业并行处理的速度。四、一个数据块在datanode上是以文件形式存储在磁盘上的,包括了两个文件,一个数据本身,一个是元数据包括数据块的长度,时间戳,数据块的校验和,每一个数据块的元数据信息大小为150byte,由于HDFS上的数据是不允许被重复上传的所以在上传之前会对上传的数据进行检查。
4、名称节点
名称节点 NameNode是HDFS的主节点,负责管理整个文件系统的命名空间和各种的元数据,包括但不限于文件/目录结构、文件权限、块ID/大小/数量、副本策略等等,其保存了两个核心的数据结构(FsImage 和 EditLog)用来存储元数据信息。同时NameNode 还维护了数据节点和文件块的映射关系,但并不是持久化存储这些数据的,而是在系统每一次启动时扫描所有的数据节点重构这些信息。FsImage 用于维护整个文件树以及文件树中所有文件和文件夹的元数据。EditLog 用于维护所有针对文件的创建、删除、重命名等操作。第一次启动:需要格式化nameNode ,创建fsimage,edits,并需要加载fsiamge。如果不是第一次启动:NameNode启动时,首先会将FsImage的内容加载到内存中,然后执行EditLog 文件中的各项操作,使得内存中的元数据保持一个最新。这项操作结束后,就会创建一个新的FsImage 文件和一个空的EditLog文件。安全模式:当NameNode 在启动过程中一直处于“安全模式”,只对外提供读操作,无法提供写操作。启动结束后,系统就会退出安全模式,对外提供写操作。在安全模式下,各个DataNode 会向NameNode发送最新数据块列表,让NameNode 得到数据块的位置信息,并对每一个文件对应的数据块副本进行统计,当“最小副本条件”满足时,NameNode 会在30秒之后退出安全模式。所谓的“最小副本条件”是指整个文件系统中 一定比例的数据块都到达最小副本数,系统会退出安全模式。当NameNode启动成功并进入正常的运行状态后,所有对于HDFS 的更新操作都会写入到EditLog,而不是直接写入FsImage。这是因为FsImage 文件通常都是比较大的,如果所有的更新操作都直接往FsImage文件中添加会使得系统变得非常缓慢。相对而言,EditLog 通常要比FsImage 小得多,将更新操作写入到EditLog 更加高效。dfs.replication:设置数据块应该被复制的份数dfs.replication.min:所规定的数据块副本的最小副本数; 副本数按dfs.replication设置,如果有失效节点导致某数据块副本数降低,当低于dfs.replication.min后,系统再在其他节点处复制新的副本dfs.safemode.threshold.pct(缺省值0.999f):指定应有多少比例的数据块满足最小副本数要求;当小于这个比例, 那就将系统切换成安全模式,对数据块进行复制;当大于该比例时,就离开安全模式,说明系统有足够的数据块副本数,可以对外提供服务;如果该值设置为小于等于0意味不进入安全模式,大于1意味一直处于安全模式。在启动一个刚刚格式化的HDFS时系统不会进入安全模式,因为没有数据块。
5、数据节点
数据节点DataNode 是HDFS 的工作节点,负责数据存储和读取,会根据客户端或者NameNode的调度进行数据的存储和检索。DataNode启动后会向nameNode进行注册,通过后,会周期性(默认1小时)的向namenode上报自己的datanode上的块信息。数据节点存储的数据会被保存在各自节点的本地Linux文件系统中。心跳报告,每3秒钟向nameNode进行汇报,心跳的返回结果中带有NameNode 带给该datanode复制数据块,移动数据块的命令, 如果说超过了10分钟datanode没有响应 ,则就会认为这个datanode节点不可用,会选择其他的机器。一个数据块在datanode上是以文件形式存储在磁盘上的,包括了两个文件,"一个数据本身,一个是元数据包括数据块的长度,时间戳,数据块的校验和",由于HDFS上的数据是不允许被重复上传的所以在上传之前会对上传的数据进行检查 。数据完整性:1、当DataNode 读取Block 的时候,他会计算CheckSum2、如果计算后CheckSum,与Block 创建时不一致,说明此block 损坏3、Client 读取其他的DataNode 上的Block4、DataNode在其文件创建后周期验证CheckSum
6、第二名称节点
secondaryNameNode存在于hadoop1.x 中,hadoop2.x采用的高可用热备在名称节点运行期间,HDFS会不断发生更新操作,这些更新操作都会被直接写入到EditLog,造成EditLog 的文件大小不断增加。在名称节点运行期间,不断增大的EditLog通常不会系统性能产生较大的影响。当名称节点重启时,首先会将FsImage 加载到内存中,然后逐个执行EditLog 中的记录。如果EditLog 文件较大,就会导致这个过程非常缓慢,使得名称节点一直处于“安全模式”,无法对外提供写操作,影响用户的使用。为了解决EditLog 逐渐增大所带来的问题,HDFS 引入了SecondaryNameNode(第二名字节点)。第二名称节点具有两个大功能:一、可以完成EditLog 和 FsImage 的合并操作,减小EditLog 的文件大小,缩短名称节点的重启时间。二,充当名称节点的检查点,保存名称节点的元数据。FsImage 和 EditLog 的合并操作,该合并过程叫做checkpoint。每隔一段时间SecondaryNameNode 就会给和NameNode 进行通信,请求停止使用Editlog 文件,暂时将最新的更新操作写入到Editlog.new 文件中。然后SecondaryNameNode 就会将NameNode中的FsImage 和 EditLog拉回到本地,然后加载到内存中,并对二者执行合并操作,即逐条执行Editlog 文件中的操作,使得FsImage 保持最新。合并结束后,SecondaryNameNode就会将最新的FsImage 发送到NameNode,NameNode 就会将最新的FsImage替换旧的FsImage,同时用Editlog.new 替换Editlog 文件,从而来减少Editlog 文件大小。
充当NameNode的“检查点”(checkpoint判断条件:① 定时时间到,默认1小时 ② edits中造作动作次数已满,默认100万次)。检查点是给secondarynamenode设置的,通过设置hdfs-site.xml中参数dfs.namenode.checkpoint.period 检查周期 和dfs.namenode.checkpoint.txns 定义NameNode上的未经检查的事务的数量,这将强制紧急检查点,即使尚未达到检查点周期。默认为100w次 来触发,只要达到这两个条件之一就可以出发secondarynamenode执行检查点的操作。
(1)通常情况下,SecondaryNameNode每隔一小时执行一次。? [hdfs-default.xml]? <property>? <name>dfs.namenode.checkpoint.period</name>? <value>3600</value>? </property>(2)一分钟检查一次操作次数,当操作次数达到1百万时,SecondaryNameNode执行一次。? <property>? <name>dfs.namenode.checkpoint.txns</name>? <value>1000000</value>? <description>操作动作次数</description>? </property><property><name>dfs.namenode.checkpoint.check.period</name><value>60</value><description> 1分钟检查一次操作次数</description></property > ```java每隔一段时间SecondaryNameNode 就会给和NameNode 进行通信,将NameNode中的FsImage 和 EditLog拉回到本地,并对二者执行合并操作得到最新的FsImage。从这个角度看,SecondaryNameNode 可以充当NameNode的检查点,因为它周期性的备份名称节点的元数据信息,当名称节点发生故障后,就可以利用SecondaryNameNode中记录的元数据信息进行系统的恢复。如果在对FsImage 和 EditLog合并期间NameNode发生故障,系统就会丢失部分元数据信息,所以在NameNode 发生故障时,HDFS并不支持将系统直接切换到SecondaryNameNode。即SecondaryNameNode 只是充当NameNode检查点并不能起到“热备份”的作用。注意:secondarynamenode并非NameNode的热备,secondarynamenode定期合并fsimage和edits,推送给NameNode,辅助NameNode,分担其工作量;在紧急情况下,可辅助恢复NameNode。```
http://c.biancheng.net/view/3574.html(HDFS读取和写入数据简介)
*7、读取流程
1、客户端调用DistributedFileSystem 的 Open()方法打开文件。 2、DistributedFileSystem 通过RPC 连接到NameNode,请求获取文件的数据块信息;NameNode返回文件的部分或者全部数据块。对于每一个数据块,NameNode 都会返回该数据块副本的DataNode 地址;最后DistributedFileSystem 返回FSDataInputStream对象给客户端,用来读取数据。 3、客户端调用FSDataInputStream 的Read() 方法来读取数据。 4、FSDataInputStream 连接保存此文件第一个数据块的最近的DataNode,并"以数据流的形式读取"数据,客户端多次调用read() 方法直到达到数据块的结束位置。 5、FSDataInputStream 连接保存此文件第二个数据块的最近的DataNode,并以数据流的形式读取数据,以此类推。 6、当客户端读取完所有数据块的数据后,调用FSDataInputStream.close()方法>
import org.apache.hadoop.conf.Configuration; import org.apache.hadoop.fs.*; public static void read (String path) throws IOException { System.out.println(">>>>>>>>>>>>>>>>>>读取文件<<<<<<<<<<<<<<<<<<<<");System.out.println("1、获取hdfs API 的配置类");Configuration configuration =new Configuration();System.out.println("2、根据配置类获取文件系统");FileSystem fileSystem=FileSystem.get(configuration);//打开路径,获取数据输入流FSDataInputStream inputStream = fileSystem.open(new Path(path));System.out.println("3、文件读取");//创建输入流读取器,并方到buffer中BufferedReader lines= new BufferedReader(new InputStreamReader(inputStream));String line=null;while ((line=lines.readLine())!=null){ System.out.println("文件内容为:"+line);}inputStream.close();lines.close();System.out.println("4、文件读取完毕,关闭文件系统");fileSystem.close();System.out.println(">>>>>>>>>>>>>>>>>>>>>>>>>Over<<<<<<<<<<<<<<<<<<<<<<<<<");}
*8、写入流程
1、客户端调用 DistribuedFileSystem 的 Create() 来创建文件; 2、 DistribuedFileSystem 通过RPC 连接NameNode,请求在文件系统的命名空间中创建一个新的文件;NameNode 首先判断文件是否存在,并且判断客户端是否拥有创建文件的权限,然后创建新文件;DistributedFileSystem 返回 FSDataOutputStream 给客户端用于写数据。3、客户端调用FSDataOutputStream的write()方法,用于向对应的文件中写入数据。 4、当客户端开始写文件时,FSDataOutputStream 会将文件切分成多个分包(Packet),并写入到其内部的数据队列。FSOutputStream 向 NameNode申请用来保存文件和副本数据块的若干个DataNode,这些 DataNode 形成一个数据流管道。队列中的分包被打包成数据包,发送到数据流管道中的第一个 DataNode。第一个 DataNode 将数据包发送给第二个 DataNode,第二个 DataNode 将数据包发送到第三个 DataNode。这样,数据包会流经管道上的各个 DataNode。5、为了保证所有的DataNode数据都是准确的,接收到数据的DataNode都会向发送者发送确认包ACK Packet。确认包沿着数据流管道反向而上,从数据流管道依次经过各个 DataNode,并最终发往客户端。当客户端收到应答时,它将对应的分包从内部队列中移除。6) 不断执行第 (3)~(5)步,直到数据全部写完。7) 调用 FSOutputStream 的 Close() 方法,将所有的数据块写入数据流管道中的数据结点,并等待确认返回成功。最后通过 NameNode 完成写入。
public static void write (String path,String content) throws IOException { System.out.println(">>>>>>>>>>>>>>>>>>写入文件<<<<<<<<<<<<<<<<<<<<"); System.out.println("1、获取hdfs API 的配置类"); Configuration configuration =new Configuration(); System.out.println("2、根据配置类获取文件系统"); FileSystem fileSystem=FileSystem.get(configuration); FSDataOutputStream outputStream = fileSystem.create(new Path(path)); System.out.println("3、文件写入"); outputStream.write(content.getBytes()); outputStream.close(); System.out.println("4、文件写入完毕,关闭文件系统"); fileSystem.close(); System.out.println(">>>>>>>>>>>>>>>>>>>>>>>>>Over<<<<<<<<<<<<<<<<<<<<<<<<<"); }
10、HA 高可用
1、前提:在HDFS中NameNode是系统的核心节点,存储各类元数据,并负责管理文件系统的命名空间和客户端段对于文件的访问。 但是在HDFS1.0 中,只存一个NameNode,一旦发生“单点故障”,就会造成整个系统失效。虽然存在SeconderyNameNode,但是它并不是NameNode的热备份。SeconderyNameNode的主要作用就是周期性的从NameNode拉取FSImage 和 EditLog 进行合并,合并完成后生成新的FSImage,并将新FSImage发送给NameNode以替换掉旧的FsImage,从而为了防止Editlog 过大导致NameNode 重启时消耗的大量的时间。由于SeconderyNameNode 无法提供“热备份”的功能,当NameNode 发生故障时,无法立即切换到SeconderyNameNode对外提供服务,需要停机恢复。2、HA 的基本介绍为了解决NameNode单点故障所带来的问题,HDFS2.0采用了HA(High Availability)架构。在HA集群中,一般设置两个NameNode,其中一个处于“活跃(Active)”状态,另一个处于“待命(Standby)”状态。只有处于Active状态的NameNode负责对外处理所有客户端的请求,处于StandBy状态的NameNode充当Active NameNode的热备份节点,在Active节点发生故障时,立即切换到活跃状态对外提供服务。因为Standby NameNode是Active NameNode的热备份,因此Active NameNode的状态信息必须实时同步到StandbyNameNode。针对状态同步,可以借助一个共享存储系统来实现,如NFS(NetworkFile System)、QJM(Quorum Journal Manager)或者Zookeeper。Active NN将 EditLog写入到共享存储系统,Standby NN会一直监听该系统,一旦发现有新的写入,就立即从公共存储系统中读取这些editLog并加载到自己内存中,从而保证与Active NN状态一致。此外,NameNode保存了数据块到实际存储位置的映射信息,即每个数据块是由哪个DateNode存储的。当一个DataNode加入到集群中时,它会把自己所包含的数据块列表给NameNode,并会周期性(默认1小时)的向namenode上报自己的datanode上的块信息,以确保NN中的块映射是最新的。因此,为了实现故障时的快速切换,必须保证StandbyNN中也包含最新的块映射信息,为此需要给DN配置Active和Standby两个NN的地址,把块的位置和心跳信息同时发送到两个NN上。为了防止出现“脑裂”现象,还要保证在任何时刻都只有一个NN处于Active状态,需要Zookeeper实现。3、如何共享EditLog 日志在HA实现中还有一个非常重要的部分就是Active Namenode和Standby Namenode之间如何共享editlog日志文件。Active Namenode会将日志文件写到共享存储,Standby Namenode会实时的监听共享存储,当共享存储发生变化时,Standby Namenode读取editlog文件,然后合并到Standby Namenode的命名空间中。在Hadoop2.6中,提供了QJM(Quorum Journal Manager)仲裁日志管理者。方案来解决HA共享存储问题。基于 QJM 的共享存储系统主要用于保存 EditLog,并不保存 FSImage 文件。FSImage 文件还是在 NameNode 的本地磁盘上。 。QJM 共享存储采用多个称为 JournalNode 的节点组成的 JournalNode 集群来存储 EditLog(默认的JournalNode 的个数为奇数个)。每个 JournalNode保存同样的 EditLog 副本,每次 NameNode 写 EditLog 的时候,除了向本地磁盘写入EditLog 之外,也会并行地向 JournalNode 集群之中的每一个 JournalNode 发送写请求,只要大多数 (majority) 的 JournalNode 节点返回成功就认为向 JournalNode 集群写入EditLog 成功。如果有 2N+1 台 JournalNode,那么根据大多数的原则,最多可以容忍有 N台 JournalNode 节点挂掉。3.1、如何使用JournalNode 集群同步数据Active NameNode 首先把 EditLog 提交到 JournalNode 集群,然后 Standby NameNode 再从JournalNode 集群定时同步 EditLog
3.2、如何使用JournalNode 集群数据恢复当前 Active NameNode 发生了异常退出,处于 Standby 状态的 NameNode 转换为 Active 状态的时候需要注意两个小问题:(1)由于 JournalNode 集群中各个 JournalNode 上的 EditLog就可能会处于不一致的状态,所以首先要做的事情就是让 JournalNode 集群中各个节点上的EditLog 恢复为一致。(2)当前处于 Standby 状态的 NameNode 的内存中的文件系统镜像有很大的可能是落后于旧的 Active NameNode 的,所以在JournalNode 集群中各个节点上的EditLog 达成一致之后,接下来Standby 状态的 NameNode要做的事情就是从 JournalNode 集群上补齐落后的EditLog。只有在这两步完成之后,当前新的 Active NameNode 才能安全地对外提供服务。
3.3、Quorum Journal JourNalNode(JN): 运行在“N台独立的物理机器上”,它将editlog文件保存在JournalNode的本地磁盘上,同时JournalNode还对外提供RPC接口QJournalProtocol以执行远程读写editlog文件的功能QuorumJournalManager(QJM):“运行在NameNode上”(目前HA集群只有两个Namenode),通过调用RPC接口QJournalProtocol中的方法向JournalNode发送写入、排斥、同步editlog优点:1. JN进程可以运行在普通的PC上,而无需配置专业的共享存储硬件。2. 不需要单独实现fencing机制,Quorum Journal模式中内置了fencing功能。3. Quorum Journa不存在单点故障,集群中有2N+1个Journal,可以允许有N个Journal Node死亡。4. JN不会因为其中一个机器的延迟而影响整体的延迟,而且也不会因为JN数量的增多而影响性能(因为Namenode向JournalNode发送日志是并行的)4. 自动故障转移机制 自动故障转移为HDFS部署增加了两个新组件:Zookeeper 和 ZKFailoverController (主备切换控制器) HA的自动故障转移依赖于Zookeeper的一下功能:(1)故障检测:集群中每一个NameNode 在Zookeeper 中维护了一个持久会话,如果机器崩溃Zookeeper 中的会话就会终止,Zookeeper 就会通知另一个NameNode 需要触发故障转移。(2)现役NameNode选择:Zookeeper 提供了一个简单的机制用于唯一的选择一个节点为active 状态。如果目前现役的NameNode 崩溃,另外一个节点可以从ZooKeeper 中获取“特殊的”排外锁以表明它应该成为现役的NameNode。 ZKFC是自动故障转移的另一个新的组件,ZKFC 是ZooKeeper的客户端。每一个NameNode 主机都会运行一个ZKFC 进程,具有以下功能:(1)健康检测:ZKFC 使用一个健康检测指令定期地去ping 与之相同主机的NameNode,只要NameNode 及时返回健康状态,ZKFC 就认为该节点是健康的。如果节点崩溃了,健康检测器就会标识该节点为不健康的。(2)ZooKeeper 会话管理:如果本地NameNode 是健康的,ZKFC 会保持一个在ZooKeeper 中打开的会话。如果本地NameNode 处于active 状态,ZKFC 也会保持一个特殊的znode锁。该锁使用了ZooKeeper 对于短暂节点的支持,如果会话终止,锁节点也会被删除。(3)基于ZooKeeper 的选择:如果本地NameNode 是健康的,且ZKFC 没有发现其他节点当前持有znode 锁,他将为自己获取该锁。如果成功了,则它已经赢得了选择,并负责运行“故障转移进程”以使得它的本地NameNode 为Active。4.1 Zookeeper 只是补充ZNode 有两种类型:临时节点 和 持久节点。ZNode 的类型在创建的时候确定并且之后不需要再修改。短暂Znode的客户端会话结束时,Zookeeper 会将短暂的Znode 删除。持久Znode不依赖于客户端会话,只有客户端明确要删除该持久的Znode 时才会被删除。
?
11、HDFS 联邦制
HDFS Federation是解决NameNode单点问题的水平横向扩展方案.1、虽然HDFS HA 解决了“单点故障的问题”,但是在系统的扩展性、整体性能和隔离性方面仍然存在问题。系统扩展性:元数据存储于NameNode的内存中,受NameNode 内存上限的制约。整体性能:吞吐量受到单个NameNode的影响。隔离性方面:一个程序的运行会影响到其他的运行程序,例如一个程序消耗了过多的资源导致其它程序无法运行。单点故障(没有完全解决):虽然namenode/namespace存在多个,但对于单个namenode来说,仍然存在单点故障。 2、HDFS联邦解决了上述问题在HDFS 联邦中,设计了多个相互独立的NameNode,这使得HDFS的命名服务得到了水平扩展。这些NameNode只管理属于自己的命名空间和块,不需要彼此协调。每一个命名空间管理属于自己的一组块,这些属于同一命名空间的块组成了一个“块池”。但是块池中的各个块实际上存在不同的DataNode中的。即DataNode 为集群中所有的NameNode 提供公共存储。每一个DataNode 要向集群中所有的NameNode进行注册,并周期性的发送心跳信息和块信息,报告自己的状态。3、namespace:由目录、文件、块组成;支持创建、删除、修改、列举命名空间相关系统的操作 4、优点 HDFS 联邦解决了以下问题系统扩展性:元数据存储于NameNode的内存中,受NameNode 内存上限的制约。整体性能:吞吐量受到单个NameNode的影响。隔离性方面:一个程序的运行会影响到其他的运行程序,例如一个程序消耗了过多的资源导致其它程序无法运行。单点故障(没有完全解决):。虽然namenode/namespace存在多个,但对于单个namenode来说,仍然存在单点故障。 5、不足HDFS Federation并没有完全解决单点故障问题。虽然namenode/namespace存在多个,但对于单个namenode来说,仍然存在单点故障。如果某个namenode挂掉了,其管理的相应文件便不可以访问。6、简言之是:单个NameNode 压力过大,受到内存的限制;元数据进行分治并且元数据访问隔离,复用DataNode存储;DN目录隔离block;
二、小问题
1、脑裂脑裂(split-brain),指在一个高可用(HA)系统中,当联系着的两个节点断开联系时,本来为一个整体的系统,分裂为两个独立节点,这时两个节点开始争抢共享资源,结果会导致系统混乱,数据损坏。在实际中,NameNode 可能会出现这种情况,NameNode 在垃圾回收(GC)时,可能会在长时间内整个系统无响应,因此,也就无法向 zk 写入心跳信息,这样的话可能会导致临时节点掉线,备 NameNode 会切换到 Active 状态,这种情况,可能会导致整个集群会有同时有两个 NameNode,这就是脑裂问题。 脑裂问题的解决方案是隔离(Fencing) HDFS提供了三个级别的隔离机制(fencing): 1.共享存储隔离:同一时间只允许一个Namenode向JournalNodes写入editlog数据。 2.客户端隔离:同一时间只允许一个Namenode响应客户端的请求。 3.Datanode隔离:同一时间只允许一个Namenode向Datanode下发名字节点指令,例如删除、复制数据块指令等等。
2、小文件解决方案"为了缓解大量小文件给namenode带来的内存压力,Hadoop 0.18.0 引入了 Hadoop Archive(Har File)。其本质是上是构建在HDFS 之上的分层文件系统,通过使用 hadoop archive 命令 就可以创建一个HAR文件。而这个命令实际上也是运行了一个 MapReduce 任务来将小文件打包成 HAR 文件。在命令行下,用户可使用一个以har://开头的URL就可以访问HAR文件中的小文件。使用HAR files可以减少HDFS中的文件数量。"创建har文件: hadoop --config /etc/xdata/conf/YARN/ archive -archiveName teach.har -p /user/liuhao/teach /user/liuhao/teach1 检索har文件:hadoop fs -ls har:///user/liuhao/teach1/teach.har下图为HAR的文件结构,可以看到访问一个小文件时需要访问两层索引文件才能获取小文件在HAR 文件中的存储位置,因此访问一个HAR 文件的效率会比直接访问HDFS文件低。对于一个MR 任务来说,如果使用HAR 文件作为输入,仍旧是每一个小文件对应map task,效率低下。所以,Har File 最好用于文件的归档
(2)Sequence Files方案"Sequence Files 文件是hadoop用来存储二进制形式的【key,value】而设计的一种平面文件。其核心是以文件名为Key,文件内容为value。可以将SequenceFile当做是一个容器,把所有文件打包到SequenceFile类中可以高效的对小文件进行存储和处理。"在存储结构上,SequenceFile主要由一个header后跟多条Recorder组成。"Header 的主要包含Key classname,value classname,存储压缩算法,用户自定义元数据等信息",同时还包含了一些同步标识,用于快速的定位到记录的边界。"每条Recorder以键值对的方式进行存储,用来表示它的字符可以一次解析成:记录的长度、key的长度、key的值和value 值",并且value 值得结构取决于该记录是否被压缩。 SequenceFile有三种压缩方案:A.无压缩类型:如果没有启用压缩(默认设置)那么每个记录就由它的记录长度(字节数)、键的长度,键和值组成。长度字段为4字节。B.记录压缩类型:记录压缩格式与无压缩格式基本相同,不同的是值字节是用定义在头部的编码器来压缩。注意:键是不压缩的。下图为记录压缩:
C.块压缩类型:块压缩一次压缩多个记录,因此它比记录压缩更紧凑,而且一般优先选择。当记录的字节数达到最小大小,才会添加到块。该最小值由io.seqfile.compress.blocksize中的属性定义。默认值是1000000字节。格式为记录数、键长度、键、值长度、值。下图为块压缩:
SequenceFile优点:A.支持基于记录(Record)或块(Block)的数据压缩。B.支持splitable,能够作为MapReduce的输入分片。C.修改简单:主要负责修改相应的业务逻辑,而不用考虑具体的存储格式。
3、数据负载均衡Hadoop的HDFS集群非常容易出现机器与机器之间磁盘利用率不平衡的情况,例如:当集群内新增、删除节点,或者某个节点机器内硬盘存储达到饱和值。当数据不平衡时,Map任务可能会分配到没有存储数据的机器,这将导致网络带宽的消耗,也无法很好的进行本地计算。当HDFS负载不均衡时,需要对HDFS进行数据的负载均衡调整,即对各节点机器上数据的存储分布进行调整。从而,让数据均匀的分布在各个DataNode上,均衡IO性能,防止热点的发生。进行数据的负载均衡调整,必须要满足如下原则:(1)数据平衡不能导致数据块减少,数据块备份丢失(2)管理员可以中止数据平衡进程(3)每次移动的数据量以及占用的网络资源,必须是可控的(4)数据均衡过程,不能影响namenode的正常工作Hadoop HDFS数据负载均衡原理(1)数据均衡服务(Rebalancing Server)首先要求 NameNode 生成 DataNode 数据分布分析报告,获取每个DataNode磁盘使用情况(2)Rebalancing Server汇总需要移动的数据分布情况,计算具体数据块迁移路线图。数据块迁移路线图,确保网络内最短路径(3)开始数据块迁移任务,Proxy Source Data Node复制一块需要移动数据块(4)将复制的数据块复制到目标DataNode上(5)删除原始数据块(6)目标DataNode向Proxy Source Data Node确认该数据块迁移完成(7)Proxy Source Data Node向Rebalancing Server确认本次数据块迁移完成。然后继续执行这个过程,直至集群达到数据均衡标准
4、压缩算法