① hadoop中在HDFS中创建一个input目录,然后hadoop fs -ls命令
你创建input目录的时候是不是也用了sudo命令?这样的话就是使用了root用户来创建了input,所以生成专的是user/root/input,而不是用了hadoop这个用户属创的目录,所以没有生成/user/hadoop/input。hadoop的指令都不需要用sudo来使用root权限啊,
② 用 java遍历hadoop分布式文件系统中某个目录下的全部文件,我的hadoop是单节点的
原因:
你访问的是本地文件系统而非hdfs , 因为Configuration默认的是在core-default.xml中的属性fs.default.name默认值是file:///,表示本地文件系统。在我们new Configuration();时会默认加载core-default.xml文件,所以根据这个文件的fs.default.name值使用了本地文件系统。
解决方法:
一般安装hadoop时都是修改core-site.xml文件,这个文件设置的属性值一般使用来覆盖core-default.xml这个文件的,在core-site.xml文件中会设置fs.default.name值为hadoop的namenode的地址以及端口号,如hdfs://localhost:9000,即表示namenode是本机,也就是为分布式。所以我们在连接hdfs时需要指定连接的地址,也就是hadoop集群中core-site.xml中fs.default.name属性值。所以解决方法有三种:
1)在代码Configuration conf=new Configuration();之后手动为Configuration对象设置fs.default.name属性值,如:conf.set("fs.default.name","hdfs:localhost:9000");
2)在代码的classpath下创建一个文件,在文件中设置fs.default.name属性值,再使用conf.addResource("文件路径")将该文件添加到Configuration中;
3)直接将集群的core-site.xml添加到classpath下即可,无需手动添加到Configuration,在new Configuration时会自动加载该文件
③ HDFS和本地文件系统文件互导
初步了解一下情况,后续根据给出案例
一、从本地文件系统到HDFS
使用hdfs自带的命令
命令:hdfs dfs -FromLocal inputPath outputPath
inputPath:本地文件目录的路径
outputPath:hdfs文件目录路径,即存储路径
二、从HDFS到本地文件系统
命令:hdfs dfs -ToLocal inputPath outputPath
inputPath:hdfs文件目录
outputPath:本地文件文件目录,即本地存储路径
因为Hbas和Hive都在存储在HDFS中,所以可以通过该条命令可以把Hbase和Hive存储在HDFS中的文件复制出来。但是经过实践,通高简过这种方式复制出来的Hbase文件是乱码。Hive里的文件有时候也会乱码,这取决于Hive数据的插入方式。
三、文件在HDFS内的移动
1、从Hbase表导出数据到HDFS
命令:hbase org.apache.hadoop.hbase.maprece.Export tableName outputPaht
例子:hbase org.apache.hadoop.hbase.maprece.Export test /user/data
test为需要从Hbase中导出的表,/user/data为hdfs上的路径,即存储路径,如果最后一个参数有前缀file:// 则为本地上的文件存储系统
2、从HDFS导入到Hbase表中,需要事先建立好表结构
命令:hbase org.apache.hadoop.hbase.maprece.Export tableName inputPaht
例子:hbase org.apache.hadoop.hbase.maprece.Import test1 /态拍temp/part-m-00000
案列:
两个不同环境数据,数据导入
过程描述:
导出正式环境数据到hdfs中,然后从hdfs中导出到本地,本地传到测试环境主机,然后从本地导入到hdfs中,再从hdfs中导入到hbase中。
处理过程:
1、注意事项:1、权限问题使用hdfs:sudo -u hdfs ;
2、存放上传路径最好不要在root下
帆念羡 3、上传完成后,查看是否在使用,数据已经插入。
1、sudo -u hdfs hbase org.apache.hadoop.hbase.maprece.Export ** /hbase/**_bak (导出到hdfs中的**_bak)
2、hdfs dfs -ToLocal /hbase/sw_bak /test (导出hdfs中文件到本地test,注:提前建好目录)
3、scp -r test_bak [email protected].**:/root/test (传送目录到测试环境主机目录下,注:传到测试环境后,把文件不要放到root的目录下,换家目录下)
4、sudo -u hdfs hdfs dfs -FromLocal /chenzeng/text_bak /data (把sw传到hdfs 中,注意上传时,文件路径要对,放在data路径下比较好)
5、sudo -u hdfs hbase org.apache.hadoop.hbase.maprece.Import test /data/test_bak/part-m-0000 (注意上次文件)
6、在hbase shell 中查看test :count 'test' 确认是否上传成功
优化:
truncate ‘’
正式环境导入至hdfs中时,
可以直接在另一个环境的执行sudo -u hdfs hbase org.apache.hadoop.hbase.maprece.Import test hdfs://server243:8020/hbase**** 可以直接加主机和对应路径进行put。
④ HDFS文件
Hadoop支持的文件系统由很多(见下图),HDFS只是其中一种实现。Java抽象类 org.apache.hadoop.fs.FileSystem 定义了Hadoop中一个文件系统的客户端接口,并且该抽象类有几个具体实现。Hadoop一般使用URI(下图)方案来选取合适的文件系统实例进行交互。
特别的,HDFS文件系统的操作可以使用 FsSystem shell 、客户端(http rest api、Java api、C api等)。
FsSystem shell 的用法基本同本地shell类似,命令可参考 FsSystem shell
Hadoop是用Java写的,通过Java Api( FileSystem 类)可以调用大部分Hadoop文件系统的交互操作。更详细的介绍可参考 hadoop Filesystem 。
非Java开发的应用可以使用由WebHDFS协议提供的HTTP REST API,但是HTTP比原生的Java客户端要慢,所以不到万不得已尽量不要使用HTTP传输特大数据。通过HTTP来访问HDFS有两种方法:
两种如图
在第一种情况中,namenode和datanode内嵌的web服务作为WebHDFS的端节点运行(是否启用WebHDFS可通过dfs.webhdfs.enabled设置,默认为true)。文件元数据在namenode上,文件读写操作首先被发往namenode,有namenode发送一个HTTP重定向至某个客户端,指示以流的方式传输文件数据的目的或源datanode。
第二种方法依靠一个或多个独立代理服务器通过HTTP访问HDFS。所有集群的网络通信都需要通过代理,因此客户端从来不直接访问namenode或datanode。使用代理后可以使用更严格的防火墙策略和带宽策略。
HttpFs代理提供和WebHDFS相同的HTTP接口,这样客户端能够通过webhdfs URI访问接口。HttpFS代理启动独立于namenode和datanode的守护进程,使用httpfs.sh 脚本,默认在一个不同的端口上监听(14000)。
下图描述了
读文件时客户端与 HDFS 中的 namenode, datanode 之间的数据流动。
对上图的解释如下:
在读取过程中, 如果 FSDataInputStream 在和一个 datanode 进行交流时出现了一个错误,他就去试一试下一个最接近的块,他当然也会记住刚才发生错误的 datanode 以至于之后不会再在这个 datanode 上进行没必要的尝试。 DFSInputStream 也会在 datanode 上传输出的数据上核查检查数(checknums).如果损坏的块被发现了, DFSInputStream 就试图从另一个拥有备份的 datanode 中去读取备份块中的数据。
在这个设计中一个重要的方面就是客户端直接从 datanode 上检索数据,并通过 namenode 指导来得到每一个块的最佳 datanode。这种设计允许 HDFS 扩展大量的并发客户端,因为数据传输只是集群上的所有 datanode 展开的。期间,namenode 仅仅只需要服务于获取块位置的请求(块位置信息是存放在内存中,所以效率很高)。如果不这样设计,随着客户端数据量的增长,数据服务就会很快成为一个瓶颈。
我们知道,相对于客户端(之后就是 maprece task 了),块的位置有以下可能性:
我们认为他们对于客户端的带宽递减,距离递增(括号中表示距离)。示意图如下:
如果集群中的机器都在同一个机架上,我们无需其他配置,若集群比较复杂,由于hadoop无法自动发现网络拓扑,所以需要额外配置网络拓扑。
基本读取程序,将文件内容输出到console
FileSystemCat
随机读取
展开原码
下图描述了写文件时客户端与 HDFS 中的 namenode, datanode 之间的数据流动。
对上图的解释如下:
如果在任何一个 datanode 在写入数据的时候失败了,接下来所做的一切对客户端都是透明的:首先, pipeline 被关闭,在确认队列中的剩下的包会被添加进数据队列的起始位置上,以至于在失败的节点下游的任 何节点都不会丢失任何的包。然后与 namenode 联系后,当前在一个好的 datanode 会联系 namenode, 给失败节点上还未写完的块生成一个新的标识ID, 以至于如果这个失败的 datanode 不久后恢复了,这个不完整的块将会被删除。失败节点会从 pipeline 中移除,然后剩下两个好的 datanode 会组成一个的新的 pipeline ,剩下的 这些块的包(也就是刚才放在数据队列队首的包)会继续写进 pipeline 中好的 datanode 中。最后,namenode 注意到块备份数小于规定的备份数,他就安排在另一个节点上创建完成备份,直接从已有的块中复制就可以。然后一直到满足了备份数( dfs.replication )。如果有多个节点的写入失败了,如果满足了最小备份数的设置( dfs.namenode.repliction.min ),写入也将会成功,然后剩下的备份会被集群异步的执行备份,直到满足了备份数( dfs.replication )。
创建目录
文件压缩有两大好处:
Hadoop 对于压缩格式的是自动识别。如果我们压缩的文件有相应压缩格式的扩展名(比如 lzo,gz,bzip2 等)。Hadoop 会根据压缩格式的扩展名自动选择相对应的解码器来解压数据,此过程完全是 Hadoop 自动处理,我们只需要确保输入的压缩文件有扩展名。
Hadoop中有多种压缩格式、算法和工具,下图列出了常用的压缩方法。
表中的“是否可切分”表示对应的压缩算法是否支持切分,也就是说是否可以搜索数据流的任意位置并进一步往下读取数据,可切分的压缩格式尤其适合MapRece。
所有的压缩算法都需要权衡空间/时间:压缩和解压缩速度更快,其代价通常是只能节省少量的空间。不同的压缩工具有不同的特性:
更详细的比较如下
1.压缩性能比较
2.优缺点
另外使用hadoop原生(native)类库比其他java实现有更快的压缩和解压缩速度。特征比较如下:
使用容器文件格式结合压缩算法也能更好的提高效率。顺序文件、Arvo文件、ORCFiles、Parqurt文件同时支持压缩和切分。
压缩举例(Java)
压缩
解压缩
六、文件序列化
序列化是指将结构化数据转换为字节流以便在网络上传输或写到磁盘进行永久存储。反序列化狮子将字节流转换回结构化对象的逆过程。
序列化用于分布式数据处理的两大领域:进程间通信和永久存储。
对序列化的要求时是格式紧凑(高效使用存储空间)、快速(读写效率高)、可扩展(可以透明地读取老格式数据)且可以互操作(可以使用不同的语言读写数据)。
Hadoop使用的是自己的序列化格式 Writable ,它绝对紧凑、速度快,但不太容易用java以外的语言进行扩展或使用。
当然,用户也可以使用其他序列化框架或者自定义序列化方式,如 Avro 框架。
Hadoop内部还使用了 Apache Thrift 和 Protocal Buffers 来实现RPC和数据交换。
⑤ 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的基本特征与构架
1.基本特征
(1)大规模数据分布存储能力:以分布式存储能力和良好的可扩展性。(基于大量分布节点上的本地文件系统,构建一个逻辑上具有巨大容量的分布式文件系统,并且整个文件系统的容量可随集群中节点的增加而线性扩展)
(2)高并发访问能力:提供很高的数据访问宽带(高数据吞吐率),并且可以把带宽的大小等比例扩展到集群中的全部节点上
(3)强大的容错能力:(设计理念中硬件故障被视作常态)保证在经常有节点发生硬件故障的情况下正确检测硬件故障,并且能自动从故障中快速恢复,确保数据不丢失(采用多副本数据块形式存储)
(4)顺序式文件访问:(大数据批处理都是大量简单数据记录的顺序处理)对顺序读进行了优化,支持大量数据的快速顺序读出,代价是对于随机的访问负载较高
(5)简单的一致性模型(一次写多次读):支持大量数据的一次写入,多次读取;不支持已写入数据的更新操作,但允许在文件尾部添加新的数据
(6)数据块存储模式:默认的块大小是64MB。好处:减少元数据的数量,允许这些数据块通过随机方式选择节点,分布存储在不同地方
2.基本框架与工作过程
(1)基本组成结构与文件访问过程
[1]HDFS;一个建立在一组分布式服务器节点的本地文件系统之上的分布式文件系统(采用经典主-从结构)
[2]主控节点NameNode:
1)是一个主服务器,用来管理整个文件系统的命名空间和元数据,以及处理来自外界的文件访问请求
2)保存了文件系统的三中元数据
命名空间:整个分布式文件系统的目录结构
数据块与文件名的映射表
每个数据块副本的位置信息,每一个数据块默认有3个副本
[3]从节点DataNode:
1)用来实际存储和管理文件的数据块
2)为了防止数据丢失,每个数据块默认有3个副本,且3个副本会分别复制在不同节点上,以避免一个节点失效造成一个数据块的彻底丢失
[4]程序访问文件时,实际文件数据流并不会通过NameNode传送,而是从NameNode获得所需访问数据块的存储位置信息后,直接去访问对应的DataNode获取数据
[5]设计好处:
1)可以允许一个文件的数据能同时在不同DataNode上并发访问,提高数据访问的速度
2)减少NameNode的负担,避免使NameNode成为数据访问瓶颈
[6]基本访问过程:
1)首先,用户的应用程序通过HDFS的客户端程序将文件名发送至NameNode
2)NameNode接收到文件名之后,在HDFS目录中检索文件名对应的数据块,再根据数据块信息找到保存数据块的DataNode地址,讲这些地址回送到客户端
3)客户端接收到这些DataNode地址之后,与这些DataNode并行的进行数据传输操作,同时将操作结果的相关日志提交到NameNode
2.数据块
(1)为了提高硬盘的效率,文件系统中最小的数据读写单元是数据块
(2)HDFS数据块的默认大小是64MB,实际部署中,可能会更多
(3)将数据块设置大的原因是减少寻址开销的时间
(4)当应用发起数据传输请求:
[1]NameNode首先检索文件对应的数据块信息,找到数据块对应的DataNode
[2]DataNode根据数据块信息在自身的存储中寻找相应的文件,进而与应用程序之间交换数据
[3]因为检索过程是但进行,所以要增加数据块大小,这样就可以减少寻址的频度和时间开销
3.命名空间
(1)文件命名遵循“目录/子目录/文件”格式
(2)通过命令行或者是API可以创建目录,并且将文件保存在目录中。可以对文件进行创建,删除,重命名操作
(3)命令空间由NameNode管理。所有对命名空间的改动都会被记录
(4)允许用户配置文件在HDFS上保存的副本数量,保存的副本数称作“副本因子”
4.通信协议
(1)采用TCP协议作为底层的支撑协议
(2)应用协议
[1]应用可以向NameNode主动发起TCP连接
[2]应用和NameNode交互协议称为Client协议
[3]NameNode和DataNode交互的协议称为DataNode协议
(3)用户和DataNode的交互是通过发起远程调用(RPC),并由NameNode响应来完成的。另外,NameNode不会主动发起远程过程调用请求
5.客户端:是用户和HDFS通信最常见的渠道,部署的HDFS都会提供客户端
二,HDFS可靠性设计
1.HDFS数据块多副本存储设计
(1)采用了在系统中保存多个副本的方式保存数据,且同一个数据块的多个副本会存放在不同节点上
(2)优点:
[1]采用多副本,可以让客户从不同数据块中读取数据,加快传输速度
[2]HDFS的DataNode之间通过网络传输数据,如果采用多个副本可以判断数据传输是否出错
[3]多副本可以保证某个DataNode失效的情况下,不会丢失数据
2.可靠性的设计实现
(1)安全模式:
[1]HDFS启动时,NameNode进入安全模式
[2]处于安全模式的NameNode不能做任何文本操作,甚至内部的副本创建不允许
[3]NameNode需要和各个DataNode通信,获得其中保存的数据块信息,并对数据块信息进行检查
[4]只有通过了NameNode检查,一个数据块被认为安全。当被认为安全的数据块所占比例达到某个阈值,NameNode退出
(2)SecondaryNmaeNode
[1]使用它来备份NameNode元数据,以便在其失效时能从中恢复出其上的元数据
[2]它充当NameNode的一个副本,本身并不处理任何请求。
[3]作用:周期性保存NameNode的元数据
(3)心跳包和副本重新创建
[1]心跳包:位于HDFS核心的NameNode,通过周期性的活动检查DataNode的活动
[2]检测到DataNode失效,保存在其上的数据不可用。则其上保存的副本需要重新创建这个副本,放到另外可用的地方
(4)数据一致性
[1]采用了数据校验和机制
[2]创建文件时,HDFS会为这个文件生成一个校验和,校验和文件和文件本身保存在同一空间上,
[3]传输数据时会将数据与校验和一起传输,应用收到数据后可以进行校验
(5)租约
[1]防止同一个文件被多个人写入数据
[2]NameNode保证同一个文件只会发放一个允许的租约,可以有效防止出现多人写入的情况
(6)回滚
三,HDFS文件存储组织与读写
1.文件数据的存储组织
(1)NameNode目录结构
[1]借助本地文件系统来保存数据,保存文件夹位置由配置选项({dfs.name.dir}/{/tmp/dfs/name})决定
[2]在NameNode的${dfs.name.dir}之下有3个文件夹和1个文件:
1)current目录:
文件VERSION:保存了当前运行的HDFS版本信息
FsImages:是整个系统的空间镜像文件
Edit:EditLog编辑文件
Fstime:上一次检查点时间
2)previous.checkpoint目录:和上一个一致,但是保存的是上一次检查点的内容
3)image目录:旧版本的FsImage存储位置
4)in_use.look:NameNode锁,只在NameNode有效(启动并且能和DataNode正常交互)时存在。
(2)DataNode目录结构
[1]借助本地文件系统来保存数据。保存文件夹位置由配置选项{dfs.data.dir}决定
[2]在其之下有4个子目录和2个文件
1)current目录:已经成功写入的数据块,以及一些系统需要的文件
a)文件VERSION:保存了当前运行的HDFS版本信息
b)subdirXX:当同一目录下文件超过一定限制,新建一个目录,保存多出来的数据块和元数据
2)tmp目录和blockBeingWritten目录:正在写入的数据块,是HDFS系统内部副本创建时引发的写入操作对应的数据块
3)detach目录:用于DataNode升级
4)Storage目录:防止版本不同带来风险
5)in_user.lock文件:DataNode锁。只有在DataNode有效时存在。
(3)CheckPointNode目录结构:和上一个基本一致
2.数据的读写过程
(1)数据读取过程
[1]首先,客户端调用FileSystem实例的open方法,获得这个文件对应的输入流,在HDFS中就是DFSInputStream
[2]构造第一步的输入流时,通过RPC远程调用NameNode可以获得NameNode中此文件对应的数据块保存位置,包括这个文件副本的保存位置(注:在输入流中会按照网络拓扑结构,根据与客户端距离对DataNode进行简单排序)
[3]-[4]获得此输入流后,客户端调用READ方法读取数据。输入流选择最近的DFSInputStream会根据前面的排序结果,选择最近的DataNode建立连接并读取数据。
[5]如果已达到数据块末端,关闭这个DataNode的连接,然后重新查找下一个数据块
[6]客户端调用close,关闭输入流DFSInputStream
(2)数据输入过程
[1]-[2]:客户端调用FileSystem实例的create方法,创建文件。检查后,在NameNode添加文件信息,创建结束之后,HDFS会返回一个输出流DFSDataOutputStream给客户端
[3]调用输出流的write方法向HDFS中对应的文件写入数据。
数据首先会被分包,这些分包会写入一个输出流的内部队列Data队列中,接收完整数据分包,输出流回想NameNode申请保存文件和副本数据块的若干个DataNode
[4]DFSDataOutputStream会(根据网络拓扑结构排序)将数据传输给距离上最短的DataNode,这个节点接收到数据包后传给下一个。数据在各节点之间通过管道流通,减少传输开销
[5]数据节点位于不同机器上,数据需要通过网络发送。(为保证数据节点数据正确,接收到数据的节点要向发送者发送确认包)
[6]执行3-5知道数据全部写完,DFSDataInputStream继续等待知道所有数据写入完毕并确认,调用complete方法通知NameNode文件写入完成
[7]NameNode接收到complete消息之后,等待相应数量的副本写入完毕后,告知客户端
传输过程,当某个DataNode失效,HDFS执行:
1)关闭数据传输的管道
2)将等待ACK队列的数据放到Data队列头部
3)更新正常DataNode中所有数据块版本。当失效的DataNode重启,之前的数据块会因为版本不对被清除
4)在传输管道中删除失效的DataNode,重新建立管道并发送数据包
4.HDFS文件系统操作命令
(1)HDFS启动与关闭
[1]启动过程:
1)进入到NameNode对应节点的Hadoop安装目录
2)执行启动脚本:bin/start-dfs.sh
[2]关闭过程:bin/stop-dfs.sh
(2)文件操作命令格式与注意事项
[1]基本命令格式:
1)bin/hadoop dfs-cmd <args> args-> scheme://authority/path
2)args参数基本格式前面是scheme,authority是机器地址和对应端口
a)本地文件,scheme是file
b)HDFS上文件,scheme是hdfs
(3)文件操作基本格式
[1]hadoop dfs-cat URL [URL ...]
[2]作用:将参数所指示文件内容输出到stdout
⑦ hdfs的启动流程
整理HDFS整个启动的详细过程
Namenode保存文件系统元数据镜像,namenode在内存及磁盘(fsimage和editslog)上分别存在一份元数据镜像文件,内存中元数据镜像保证了hdfs文件系统文件访问效率,磁盘上的元数据镜像保证了hdfs文件系统的安全性。
namenode在磁盘上的两类文件组成:
fsimage文件:保存文件系统至上次checkpoint为止目录和文件元数据。
edits文件:保存文件系统从上次checkpoint起对hdfs的所有操作记录日志信息。
fsimage和editlog文件可以在本地文件系统看到
首次安装格式化(format)主要作用是在本地文件系统生成fsimage文件。
1、首此启动hdfs过程:
启动namenode:
读取fsimage生成内存中元数据镜像。
启动datanode:
向namenode注册;
向namenode发送blockreport。
启动成功后,client可以对HDFS进行目录创建、文件上传、下载、查看、重命名等操作,更改namespace的操作将被记录在edits文件中。
2、之后启动HDFS文件系统过程:
启动namenode:
读取fsimage元数据镜像文件,加载到内存中。
读取editlog日志文件,加载到内存中,使当前内存中元数据信息与上次关闭系统时保持一致。然后在磁盘上生成一份同内存中元数据镜像相同的fsimage文件,同时生成一个新的null的editlog文件用于记录以后的hdfs文件系统的更改。
启动datanode:
向namenode注册;
向namenode发送blockreport。
启动成功后,client可以对HDFS进行目录创建、文件上传、下载、查看、重命名等操作,更改namespace的操作将被记录在editlog文件中。
3、SecondaryNameNode
辅助namenode,不能代替namenode。
SecondaryNameNode的主要作用是用于合并fsimage和editlog文件。在没有SecondaryNameNode守护进程的情况下,从namenode启动开始至namenode关闭期间所有的HDFS更改操作都将记录到editlog文件,这样会造成巨大的editlog文件,所带来的直接危害就是下次启动namenode过程会非常漫长。
在启动SecondaryNameNode守护进程后,每当满足一定的触发条件(每3600s、文件数量增加100w等),SecondaryNameNode都会拷贝namenode的fsimage和editlog文件到自己的目录下,首先将fsimage加载到内存中,然后加载editlog文件到内存中合并fsimage和editlog文件为一个新的fsimage文件,然后将新的fsimage文件拷贝回namenode目录下。并且声称新的editlog文件用于记录DFS的更改。
4、安全模式
在启动namenode至所有datanode启动完成前的阶段成为安全模式。在安全模式下,client只能读取部分HDFS文件信息,不允许client对HDFS的任何更改操作,比如创建目录、上传文件、删除文件、重命名文件等。
namenode推出安全模式条件需要满足以下条件:
datanodes blocks/total blocks >= 99.999% + 30s(缓冲时间) 此时安全模式才会推出
Secondary namenode工作流程:
1)secondary通知namenode切换edits文件
2)secondary通过http请求从namenode获得fsimage和edits文件
3)secondary将fsimage载入内存,然后开始合并edits
4)secondary将新的fsimage发回给namenode
5)namenode用新的fsimage替换旧的fsimage