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 仅仅只需要服务于获取块位置的请求(块位置信息是存放在内存中,所以效率很高)。如果不这样设计,随着客户端数据量的增长,数据服务就会很快成为一个瓶颈。
我们知道,相对于客户端(之后就是 mapreduce 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中有多种压缩格式、算法和工具,下图列出了常用的压缩方法。
表中的“是否可切分”表示对应的压缩算法是否支持切分,也就是说是否可以搜索数据流的任意位置并进一步往下读取数据,可切分的压缩格式尤其适合MapReduce。
所有的压缩算法都需要权衡空间/时间:压缩和解压缩速度更快,其代价通常是只能节省少量的空间。不同的压缩工具有不同的特性:
更详细的比较如下
1.压缩性能比较
2.优缺点
另外使用hadoop原生(native)类库比其他java实现有更快的压缩和解压缩速度。特征比较如下:
使用容器文件格式结合压缩算法也能更好的提高效率。顺序文件、Arvo文件、ORCFiles、Parqurt文件同时支持压缩和切分。
压缩举例(Java)
压缩
解压缩
六、文件序列化
序列化是指将结构化数据转换为字节流以便在网络上传输或写到磁盘进行永久存储。反序列化狮子将字节流转换回结构化对象的逆过程。
序列化用于分布式数据处理的两大领域:进程间通信和永久存储。
对序列化的要求时是格式紧凑(高效使用存储空间)、快速(读写效率高)、可扩展(可以透明地读取老格式数据)且可以互 *** 作(可以使用不同的语言读写数据)。
Hadoop使用的是自己的序列化格式 Writable ,它绝对紧凑、速度快,但不太容易用java以外的语言进行扩展或使用。
当然,用户也可以使用其他序列化框架或者自定义序列化方式,如 Avro 框架。
Hadoop内部还使用了 Apache Thrift 和 Protocal Buffers 来实现RPC和数据交换。
1、在HDFS之上将数据压缩好后,再存储到HDFS2、在HDFS内部支持数据压缩,这里又可以分为几种方法:
2.1、压缩工作在DataNode上完成,这里又分两种方法:
2.1.1、数据接收完后,再压缩
这个方法对HDFS的改动最小,但效果最低,只需要在block文件close后,调用压缩工具,将block文件压缩一下,然后再打开block文件时解压一下即可,几行代码就可以搞定
2.1.2、边接收数据边压缩,使用第三方提供的压缩库
效率和复杂度折中方法,Hook住系统的write和read *** 作,在数据写入磁盘之前,先压缩一下,但write和read对外的接口行为不变,比如:原始大小为100KB的数据,压缩后大小为10KB,当写入100KB后,仍对调用者返回100KB,而不是10KB
2.2、压缩工作交给DFSClient做,DataNode只接收和存储
这个方法效果最高,压缩分散地推给了HDFS客户端,但DataNode需要知道什么时候一个block块接收完成了。
推荐最终实现采用2.2这个方法,该方法需要修改的HDFS代码量也不大,但效果最高。
· 依赖软件ssh、jdk
· 环境的配置
Java_Home
免密钥
· 时间同步
· hosts、hostname
· /opt/sxt/
· 配置文件新修改
Java_Home
· 角色在哪里启动
部署参考步骤(请点击此处)
(1)设置ssh免密钥
ssh-keygen -t dsa -P '' -f ~/.ssh/id_dsa
cat ~/.ssh/id_dsa.pub >>~/.ssh/authorized_keys
此时可检验是否设置成功,尝试免密登录本机,如下
(2)安装jdk
首先利用xftp将安装包导入,再解压安装
解压后,java所在目录位置如下 /usr/java
配置环境变量,打开 vi /etc/profile 追加下面两行
保存退出后,是设置系统配置,linux下使用source /etc/profile保存配置后,新的环境变量只能在一个终端里面有效。
(3)hadoop部署
利用xftp将hadoop-2.6.5.tar.gz包上传,解压安装
新建目录存放hadoop
配置hadoop环境变量,增加如下两行
进入如下目录修改hadoop-env.sh等配置文件,首先修改hadoop-env.sh文件,改后如下
其次、修改mapred-env.sh,/usr/java/jdk1.8.0_261-amd64
修改yarn-env.sh
其次修改etc/hadoop下的core-site.xml和hdfs-site.xml,使主节点位置可知
```
<configuration>
<property>
<name>fs.defaultFS</name>
<value>hdfs://node01:9000</value>
</property>
<property>
<name>hadoop.tmp.dir</name>
<value>/var/sxt/hadoop/local</value>
</property>
</configuration>
```
```
<configuration>
<property>
<name>dfs.replication</name>
<value>1</value>
</property>
<property>
<name>dfs.namenode.secondary.http-address</name>
<value>node01:50090</value>
</property>
</configuration>
```
配置slaves文件,使DataNode可知,修改如下,如以后还有namenode,可添加
随后格式化 hdfs namenode -format 显示successfully则配置成功
启动,如报错,在查看下方日志文件排错
访问node01:50070 如下所示,成功!
计划:node01 : NameNode
node02 : SecondaryNode DataNode
node03 node04 : DataNode
(1)安装jdk,配置环境变量,设置ssh免密钥(将node01d1ssh的id_dsa.pub写到其他三个节点)
此时查看node02中.ssh下目录
或者直接将node01的authorized_keys追加到node02的.ssh下,如下所示,此时node01可以免密登录node02
之后node03和node04依次执行图3-1和图3-2的命令。校准四个系统时间
修改node01的core-site.xml
进入node01的sxt目录将hadoop-2.6.5拷贝到node02(03、04都要执行相同步骤)的同目录下(node02下的opt/sxt)
经过以上步骤配置完成,再从node01进行格式化
hdfs namenode -format
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)