龙空技术网

看完就能独自把集群搭起来!Hadoop HDFS完全分布式环境搭建详解

CSDN云计算 617

前言:

现时各位老铁们对“hadoop切片”大致比较关切,小伙伴们都想要分析一些“hadoop切片”的相关文章。那么小编同时在网摘上搜集了一些对于“hadoop切片””的相关文章,希望我们能喜欢,朋友们一起来了解一下吧!

作者 | 慢慢变成大佬

责编 | Carol

出品 | CSDN云计算(ID:CSDNcloud)

在文章开始之前,作者想要告诉大家:读懂本篇文章,能让小白快速入门,并且能够搭建完全分布式的集群,以及能对Hadoop HDFS产生详细的认知,对以后的学习有很大的帮助。

我们先来了解Hadoop的HDFS基本概念,熟知基本概念,在搭环境时能够能加得心应手。

Hadoop基本介绍

Hadoop是一个框架:Hadoop的本质其实就是一系列功能模块儿组成的框架,每个模块分别负责Hadoop的一些功能,如HDFS负责大数据的存储功能,Yarn,负责整个集群的资源调度,Common则负责Hadoop远程过程调用的实现以及提供序列化机制。Hadoop具有高容错性,以及高拓展性。Hadoop适合处理大数据数据。

1、HDFS的架构

这里对HDFS的组成架构做说明:

1)NameNode : 是HDFS的主从架构中的Master,负责维护整个文件系统的目录树,管理数据块(Block)的元数据信息,处理客户端的读写请求,并且管理Block的副本放置策略。

2)DataNode: 是HDFS的主从架构中的Slave,存放在HDFS中的文件都被分成块来存储,DataNode负责存储文件的块,对于DataNode所在的节点来说,块就是一个普通的文件,可以在DataNode存放块的目录下查看,如果不改动,默认是$(dfs.data.dir)/current),块的文件名为blk_blkID。DataNode会通过心跳机制和NameNode通信。

在集群初始化时,每个DataNode启动后都将当前存储的块的元数据信息告诉NameNode,在集群正常工作时,DataNode会不断的向NameNode通信,向它提供自己本地的信息,同时会接受来自NameNode的读写命令,来操作本地的数据块。

这个时候我们会有疑问,NameNode的元数据到底存放在哪里? 首先不可能是磁盘,因为如果存放在 磁盘,那么经常操作HDFS,效率会非常低,那么就只能会存放内存里,可是,效率虽然快了,但是如果 内存满了,或者集群停止服务,那么数据的元数据就会丢失,对于这个问题,HDFS做了一个专门用来解决 这个问题的角色,SecondaryNameNode

3)SecondaryNamenode: 是用于定期合并命名空间镜像和命名空间镜像的编辑日志的辅助守护进程,每个HDFS集群都有一个SecondaryNameNode,在生产环境下,一般SecondaryNameNode也会单独运行在一台服务器上。

FSImage文件(命名空间镜像) 可以理解为NameNode当时的内存状态或者内存中元数据序列化后形成的文件,所有信息保存做成的镜像文件,是可以被加载的。也可以理解为是文件系统元数据的一个永久的性检查点,但并不是每一个写操作都会更新这个文件,因为FSImage肯定是一个大型的文件,如果频繁地执行对这个文件进行写操作,会使系统运行极为缓慢。

解决方案是,NameNode只将改动内容预写日志(WAL),即写入命名空间镜像的编辑日志(edit log 记录客户端更新元数据信息的每一步操作)可通过Edits运算出元数据。随着时间的推移,编辑日志会变得越来越大,那么如果发生故障,将会花费非常多的时间来进行回滚操作,所以就像传统的关系型数据库一样,需要定期地合并FSImage和编辑日志。

如果由NameNode来做合并的操作,那么NameNode在为集群提供服务时可能无法提供足够的资源,那么为了彻底解决这一问题,就加入了SecondaryNameNode这个角色。

工作详解:

NameNode启动时,先滚动Edits并生成一个空的edits.inprogress,然后加载Edits和Fsimage到内存中,此时NameNode内存就持有最新的元数据信息。Client开始对NameNode发送元数据的增删改的请求,这些请求的操作首先会被记录到edits.inprogress中(查询元数据的操作不会被记录在Edits中,因为查询操作不会更改元数据信息),如果此时NameNode挂掉,重启后会从Edits中读取元数据的信息。然后,NameNode会在内存中执行元数据的增删改的操作。

由于Edits中记录的操作会越来越多,Edits文件会越来越大,导致NameNode在启动加载Edits时会很慢,所以需要对Edits和Fsimage进行合并(所谓合并,就是将Edits和Fsimage加载到内存中,照着Edits中的操作一步步执行,最终形成新的Fsimage)。SecondaryNameNode的作用就是帮助NameNode进行Edits和Fsimage的合并工作。

4)块: 每个磁盘都有默认的数据块大小,这是磁盘进行数据读/写的最小单位,文件系统也有文件块的概念,HDFS同样也有块(block)的概念,但是HDFS的块比一般文件系统的块大得多,默认为128MB,并且可以随着实际需要而变化,配置项为HDFS-site.xml文件中的dfs.block.size项。

与单一文件系统相似,HDFS上的文件也被划分为块大小的多个分块,它是HDFS存储处理的最小单元。HDFS中的块如此之大的原因是为了最小化寻址开销。如果块设置的足够大,从磁盘传输数据的时间可以明显大于定位这个块开始位置所需的时间。这样,传输一个由多个块组成的文件的时间取决于磁盘传输的效率。得益于磁盘传输速率的提升,块的大小可以被设为300 MB甚至更大。

2、HDFS的容错机制

1)心跳机制

在NameNode和DataNode之间维持心跳检测,当由于网络故障之类的原因,导致DataNode发出的心跳包没有被NameNode正常收到的时候,NameNode就不会将任何新的I/O操作派发给那个DataNode,该DataNode上的数据被认为是无效的,因此NameNode会检测是否有文件块的副本数目小于设置值,如果小于就自动开始复制新的副本并分发到其他DataNode节点。

2)检测文件块的完整性

HDFS会记录每个新创建文件的所有块的校验和。当以后检索这些文件时或者从某个节点获取块时,会首先确认校验和是否一致,如果不一致,会从其他DataNode节点上获取该块的副本。

3)集群的负载均衡

由于节点的失效或者增加,可能导致数据分布不均匀,当某个DataNode节点的空闲空间大于一个临界值的时候,HDFS会自动从其他DataNode迁移数据过来。

4)NameNode上的FSImage和编辑日志(edits log)

文件NameNode上的FSImage和编辑日志文件是HDFS的核心数据结构,如果这些文件损坏了,HDFS将失效。因而,NameNode由Secondary NameNode定期备份FSImage和编辑日志文件,NameNode在Hadoop中确实存在单点故障的可能,当NameNode出现机器故障,手工干预是必须的。

5)文件的删除

删除操作并不是马上从NameNode移出命名空间,而是存放在/trash目录随时可恢复,直到超过设置时间才被正式移除。设置的时间由hdfs-site.xml文件的配置项fs.trash.interval决定,单位为秒。

6)多副本机制

HDFS会将文件切片成块并存储至各个DataNode中,文件数据块在HDFS的布局情况由NameNode和hdfs-site.xml中的配置dfs.replication共同决定。dfs.replication表示该文件在HDFS中的副本数,默认为3,即有两份冗余。

3、副本的选择策略

Hadoop的默认布局是在HDFS客户端节点上放第一个副本,但是由于HDFS客户端有可能运行于集群之外,就随机选择一个节点,不过Hadoop会尽量避免选择那些存储太满或者太忙的节点。

第二个副本放在与第一个不同且随机另外选择的机架中的节点上。第三个副本与第二个副本放在相同的机架,且随机选择另外一个节点。其他副本(如果dfs.replication大于3)放在集群随机选择的节点上,Hadoop也会尽量避免在相同的机架上放太多副本。

4、HDFS写文件流程

1)客户端通过Distributed FileSystem模块向NameNode请求上传文件,NameNode检查目标文件是否已存在,父目录是否存在。

2)NameNode返回是否可以上传。

3)客户端请求第一个 Block上传到哪几个DataNode服务器上。

4)NameNode返回3个DataNode节点,分别为dn1、dn2、dn3。

如果有多个节点,返回实际的副本数量,并根据距离及负载情况计算

5)客户端通过FSDataOutputStream模块请求dn1上传数据,dn1收到请求会继续调用dn2,然后dn2调用dn3,将这个通信管道建立完成。

6)dn1、dn2、dn3逐级应答客户端。

7)客户端开始往dn1上传第一个Block(先从磁盘读取数据放到一个本地内存缓存),以Packet为单位,dn1收到一个Packet就会传给dn2,dn2传给dn3;dn1每传一个packet会放入一个应答队列等待应答。

8)当一个Block传输完成之后,客户端再次请求NameNode上传第二个Block的服务器。(重复执行3-7步)。

注意: 如果写入的时候,复制管道中的某一个DataNode无法将数据写入磁盘(如DataNode死机)。发生这种错误时,管道会立即关闭,已发送的但尚未收到确认的数据包会被退回到队列中,以确保管道中错误节点的下游节点可以得到数据包。而在剩下的健康的DataNode中,正在写入的数据块会被分配新的blk_id。

这样,当发生故障的数据节点恢复后,冗余的数据块就会因为不属于任何文件而被自动丢弃,由剩余DataNode节点组成的新复制管道会重新开放,写入操作得以继续,写操作将继续直至文件关闭。

NameNode如果发现文件的某个数据块正在通过复制管道进行复制,就会异步地创建一个新的复制块,这样,即便HDFS的多个DataNode发生错误,HDFS客户端仍然可以从数据块的副本中恢复数据,前提是满足最少数目要求的数据副本(dfs.replication.min)已经被正确写入(dfs.replication.min配置默认为1)。

5、HDFS读文件流程

1)客户端通过Distributed FileSystem向NameNode请求下载文件,NameNode通过查询元数据,找到文件块所在的DataNode地址。

2)挑选一台DataNode(就近原则,然后随机)服务器,请求读取数据。

3)DataNode开始传输数据给客户端(从磁盘里面读取数据输入流,以Packet为单位来做校验)。

4)客户端以Packet为单位接收,先在本地缓存,然后写入目标文件。

到这里,我们对HDFS的大部分概念已经了解了,下面则来进行完全分布式的环境搭建。

环境搭建

1. 首先准备3台虚拟机,并且要保证虚拟机的时间同步和hosts,ip都配置好,集群能互相通信。

这里可以看到,我的三台都配好了ip,而且hosts也都写了,并且集群时间同步也都已经做了。

2. 解压安装JDK,并且在/etc/profile 里面配置环境变量

通过xftp把文件传到linux本地里面 ,自己新建文件夹,放到里面 ,然后解压到自己的文件夹内。

通过tar命令进行解压并进行环境变量的配置,最后记得source配置文件。

然后我们进入Hadoop的目录看一看:

(1)bin目录:存放对Hadoop相关服务(HDFS,YARN)进行操作的脚本

(2)etc目录:Hadoop的配置文件目录,存放Hadoop的配置文件

(3)lib目录:存放Hadoop的本地库(对数据进行压缩解压缩功能)

(4)sbin目录:存放启动或停止Hadoop相关服务的脚本

(5)share目录:存放Hadoop的依赖jar包、文档、和官方案例

3. 接下来,我们进入etc目录,并且对Hadoop的配置进行修改。

我们总共要修改 core-site.xml . hadoop-env.sh . hdfs-site.xml ,mapred-env.sh, mapred-site.xml , slaves, yarn-env.sh, yarn-site.xml

首先,在上面这些配置文件后缀都是sh的,比如hadoop-env.sh,我们就只需要把JavaHome配置一下。

其他的-env.sh的也是这样,只需要配置JDK即可,这里就不多阐述 。

接下来,我们vim core-site,并配置这些东西

    <!-- 指定HDFS中NameNode的地址 -->    <property>            <name>fs.defaultFS</name>            <value>hdfs://hadoop102:9000</value>    </property>    <!-- 指定Hadoop运行时产生文件的存储目录 -->    <property>            <name>hadoop.tmp.dir</name>            <value>/opt/module/hadoop-2.7.2/data/tmp</value>    </property>  

这个就配置完成,接着,我们就配置hdfs-site.xml

  <!-- 配置块的副本数 -->    <property>        <name>dfs.replication</name>        <value>3</value>    </property>    <!-- 指定Hadoop辅助名称节点主机配置 -->    <property>          <name>dfs.namenode.secondary.http-address</name>          <value>hadoop104:50090</value>    </property>

然后配置yarn-site.xml

 <!-- 配置块的副本数 -->    <property>        <name>dfs.replication</name>        <value>3</value>    </property>    <!-- 指定Hadoop辅助名称节点主机配置 -->    <property>          <name>dfs.namenode.secondary.http-address</name>          <value>hadoop104:50090</value>    </property>

接着配置mapred-site.xml

<!-- 指定MR运行在Yarn上 --><property>    <name>mapreduce.framework.name</name>    <value>yarn</value></property>

到这里,我们Hadoop的配置就已经完成,因为是分布式,所以我们就通过scp -r 的命令把jdk,和Hadoop都拷贝过去,并且各自配置一下环境变量,并source,到这里我们完全分布式就配置完成。

然后我们可以单点启动,也可以群起,不过群起需要配置免密,免密配置很简单,就不再多说,接下来我们直接通过start-all.sh启动集群,可以通过jps查看一下。

进程全部起来了,接下来我们去webUI可以查看HDFS,端口是50070,yarn是8088

至此,我们的完全分布式搭建成功,相信大家也对搭建的过程很了解了,对Hadoop HDFS也都算是非常详细的介绍了,希望大家看完都能自己搭建一个集群,对以后的大数据学习打下基础,至于shell操作HDFS,或者JavaAPI操作,都是非常简单的,在这里简单说一下, shell操作Hadoop十分简单,部分命令和linux很像。

```powershell-mkdir 在HDFS上创建目录-moveFromLocal:从本地剪切粘贴到HDFS-appendToFile:追加一个文件到已经存在的文件末尾-cat:显示文件内容-chgrp 、-chmod、-chown:Linux文件系统中的用法一样,修改文件所属权限-copyFromLocal:从本地文件系统中拷贝文件到HDFS路径去-copyToLocal:从HDFS拷贝到本地-cp :从HDFS的一个路径拷贝到HDFS的另一个路径-mv:在HDFS目录中移动文件-get:等同于copyToLocal,就是从HDFS下载文件到本地-getmerge:合并下载多个文件,比如HDFS的目录 /user/lmr/test下有多个文件:log.1, log.2,log.3,...-put:等同于copyFromLocal-tail:显示一个文件的末尾-rm:删除文件或文件夹-rmdir:删除空目录-du统计文件夹的大小信息

至于Java的API相关操作,也是很简单的,这里就不多说。

如果你有任何意见或想法,欢迎在评论区和我们讨论!

标签: #hadoop切片