一、简介
1.1、概述
- HDFS(Hadoop Distribute File System)是Hadoop提供的分布式文件存储系统
- HDFS是仿照Google File System(GFS)来实现的
1.2、特点
- 能够存储超大文件 - 切块
- 能够快速的应对和检测故障 - 心跳
- 能够在相对廉价的机器上进行横向扩展
- 不支持低延迟的响应
- 不建议存储小文件 - 一个文件大小<Block*0.8
- 简化的一致性模型 - 一次写入多次读取,不允许修改但是允许追加写入
- 提供了流式访问模型
- 支持弱事务或者不支持事务。在样本量足够大的前提下,允许产生一定的容错误差
二、基本理论
2.1、概述
- HDFS本身是一个典型的主从(MS)结构:主节点是NameNode,从节点是DataNode
在HDFS中,会对上传的文件来进行切分,切成1个到多个数据块(Block)
HDFS会对存入的数据自动的进行备份。每一个备份称之为是一个副本(replication)。默认副本数量为3
HDFS仿照Linux设计了一套虚拟文件系统,保证上传的文件可以放在不同的路径下。HDFS的根路径是/
2.2、Block - 数据块
- Block是HDFS中数据存储的基本单位。在HDFS中,所有的文件都是以Block形式存储的
- 在Hadoop2.0中,Block的默认(最大)大小是134217728B(即128M,通过dfs.blocksize属性来调节,单位是字节,放在hdfs-site.xml文件中)
- 如果一个文件不到一个Block大小,那么这个文件本身是多大,对应的Block就是多大。例如如果一个文件只有10M,对应的Block就是10M
- HDFS会给每一个Block分配一个唯一的BlockID
- 切块的意义
a 为了能够存储超大文件
b 为了能够进行快速备份
2.3、NameNode
- NameNode是HDFS的主节点,也是HDFS的核心节点。默认情况下,Hadoop2.0集群中只有1个
NameNode,意味着存在单点故障- NameNode负责记录元数据,管理DataNode
- 元数据(metadata)是用于描述数据的数据,可以看作是一个账本
- HDFS中的元数据包含了30多个属性
- NameNode会将元数据维系在磁盘以及内存中
a 维系在磁盘中的目的是为了可靠性
b 维系在内存中的目的是为了读写快- 元数据在磁盘中的存储位置由hadoop.tmp.dir属性来决定。如果不指定,那么元数据默认是放在/tmp目录下
- dfs目录下的in_use.lock标记当前服务器是否已经启动了指定的进程
- 和元数据相关的文件
a edits:写操作文件。当NameNode接收到写请求的时候,会将请求命令记录到edits文件中
b fsimage:元映像文件。用于记录元数据的。注意,fsimage文件中的元数据和内存中的元数据不同步- 当NameNode接收到写请求的时候,会先将这个写请求记录到edits_inprogress文件。如果记录成功,那么NameNode会去修改内存中的元数据,修改完成之后,会给客户端返回一个成功信号ACK。此时,并没有修改fsimage文件中的元数据,所以fsimage文件中的元数据和内存中的元数据不是同步的
- 当达到指定条件的时候,edits_inprogress文件会滚动生成一个edits文件,同时产生一个新的edits_inprogress文件。后续来的新的写操作会继续记录到新的edits_inprogress文件中。滚动生成的edits文件中的内容会一一取出,然后再次更新fsimage文件中的元数据
- edits_inprogress文件的滚动条件
a 空间:当edits_inprogress文件达到指定大(默认是64M,通过fs.checkpoint.size属性来指定,单位是字节,放在core-site.xml文件中)小的时候,会滚动生成一个edits文件
b 时间:当距离上一次滚动达到指定的时间间隔(默认是1H,通过fs.checkpoint.period属性来指定,单位是秒,放在core-site.xml文件中)的时候,那么edits_inprogress文件也会产生滚动
c 重启:当NameNode被重启的时候,会自动的触发edits_inprogress文件的滚动
d 强制:通过hadoop dfsadmin -rollEdits命令来强制edits_inprogress文件的滚动- 在HDFS第一次启动的时候,启动之后1min,会自动产生一次滚动,生成一个edits文件。之后会按照指定的时间间隔来滚动
- 每一个fsimage文件都会对应一个md5文件,md5文件对元数据文件来进行校验
- 在HDFS中,会将每一次的写操作看作是一个事务,分配一个全局递增的事务id,简写为txid
- NameNode通过心跳机制来管理DataNode
- DataNode定时(默认是3s,通过dfs.heartbeat.interval属性来指定,单位是s,放在hdfs-site.xml中)给NameNode的心跳信号。如果超过10min,NameNode没有收到DataNode的心跳,那么此时NameNode会认为这个DataNode已经lost(丢失),那么NameNode就会将这个DataNode的数据备份到其他节点上来保证副本数量
- 心跳信号
a clusterid - 集群编号
b DataNode的状态(预服役、服役、预退役)
c DataNode中存储的Block的情况- 安全模式(safe mode)
a NameNode重启之后,会自动进入安全模式
b NameNode先将edits_inprogress文件滚动生成edits文件
c 滚动完成之后,NameNode会更新fsimage文件中的元数据
d 更新完成之后,NameNode会将fsimage文件中的元数据加载到内存中
e 加载完元数据之后,NameNode就会等待DataNode的心跳
f 如果NameNode没有收到DataNode的心跳,那么NameNode会将这个DataNode上的数据重新备份保证集群中的副本数量
g 如果NameNode收到DataNode的心跳,会校验心跳信息。如果校验成功,则NameNode会自动退出安全模式;如果校验失败,则NameNode会试图恢复数据,恢复完成之后,会重新校验- 如果在实际生产过程中,发现NameNode处在安全模式中,需要等待一段时间;如果在合理的时间内,NameNode都没有退出安全模式,那么说明数据产生了不可逆的丢失,此时需要强制退出安全模式:hadoop dfsadmin -safemode leave
- 在安全模式下,HDFS集群只提供读服务不提供写服务
- 正因为安全模式的存在,所以副本数量不能超过节点数量
2.4、DataNode
- DataNode是用于存储数据的,数据是以Block形式来存储
- DataNode将数据存储在磁盘上,在磁盘上的存储位置由hadoop.tmp.dir属性来决定
- DataNode的状态:预服役、服役、预退役、退役、丢失
2.5、SecondaryNameNode
- SecondaryNameNode并不是NameNode的备份,而是辅助NameNode完成edits_inprogress文件的滚动和fsimage文件的更新
- 如果在集群中存在SecondaryNameNode,那么edits_inprogress文件的滚动和fsimage文件的更新由SecondaryNameNode来完成;如果集群中没有SecondaryNameNode,那么上述这些操作由NameNode自己完成
- 到目前为止,在Hadoop2.0中只支持两种结构
a 1个NameNode+1个SecondaryName+n个DataNode
b 2个NameNode(Active+Standby)+n个DataNode- 在HDFS中,NameNode处在核心位置,如果NameNode宕机,那么HDFS集群就无法对外提供服务,所以必须考虑对NameNode来进行备份。在这种情况下,就会选择上述的第二种结构来搭建集群,来保证NameNode的高可用
2.6、副本放置策略
- 在HDFS中,默认支持的是多副本策略。如果不指定,则默认情况下副本数量为3。通过dfs.replication属性来决定,放在hdfs-site.xml中
- 如果没有开启机架感知策略的前提下,HDFS中的多个副本是放在相对空闲的节点上
- 如果开启了机架感知策略,那么HDFS在放置副本的时候就需要使用副本放置策略
a 第一个副本
集群内部上传:谁上传就放在谁身上
集群外部上传:谁空闲就放在谁身上
b 第二个副本
Hadoop2.7之前:第二个副本放在和第一个副本不同机架的节点上
Hadoop2.7开始:第二个副本放在和第一个副本相同机架的节点上
c 第三个副本
Hadoop2.7之前:第三个副本放在和第二个副本相同机架的节点上
Hadoop2.7开始:第三个副本放在和第二个副本不同机架的节点上
更多副本:谁空闲就放在谁身上
2.7、机架感知策略
- 机架感知策略默认是不开启的
- 如果需要开启机架感知策略,那么需要在hadoop-site.xml文件中通过tepology.script.file.name属性来指定,属性值的是脚本文件的名字
- 脚本文件可以是Python/Shell脚本,需要在这个脚本文件中定义一个Map来存储机架结构。在这个Map中,键是主机名或者是IP,值是机架名。只要值一致,那么就表示将键对应的节点配置了同一个机架上
- 机架感知策略中的机架,实际上是一个逻辑机架,也就意味着可以将不同物理机架上的节点配置在同一个逻辑机架上。但是在实际生产过程中,为了方便管理,往往会将同一个物理机架上的节点配置在同一个逻辑机架上
2.8、基本命令
2.9、回收站机制
- 默认情况下,HDFS的回收站机制是不开启的,也就意味着删除命令会立即生效且不可逆
- 开启回收站
三、流程
3.1、上传/写流程
- 客户端发起RPC请求到NameNode,请求上传文件
- NameNode收到请求之后,先进行校验
a 先校验是否有写入权限
b 再校验是否有同名文件 - FileAlreadyExistException- 如果校验失败,则会报错;如果校验成功,那么NameNode会给客户端返回一个成功信号表示允许上传
- 客户端收到成功信号之后,会再次发起请求,请求获取第一个Block的存储位置
- 当NameNode收到请求之后,会将这个Block的存储位置(DataNode的主机名/IP)放到队列中返回给客户端。默认情况下,一个Block对应了3个副本,所以队列中默认会放3个DataNode的主机名/IP
- 当客户端收到队列之后,会将位置从队列中全部取出来,然后从这些位置中选取较近(网络拓扑距离的远近)的节点将当前Block的第一个副本写入
- 第一个副本所在的节点会通过pipeline(管道,本质上就是NIO中的Channel)将这个Block的第二个副本写入到对应的节点上。第二个副本写完之后,通过pipeline将数据写到第三个副本所在的节点上
- 当最后一个副本写完之后,这个副本所在的节点会给上一个副本所在的节点返回一个ACK信号,依次前推。直到第一个副本所在的节点也收到ACK,那么会给客户端来返回一个ACK
- 当客户端收到ACK之后,会向NameNode发送请求,请求获取下一个Block的地址,重复5.6.7.8.9步骤,直到所有的Block全部写完
- 当所有的Block写完之后,客户端会给NameNode发送一个结束信号。NameNode在收到信号之后会关闭这个文件(实际上就是关流)。文件一旦关闭,就不能修改
3.2、下载/读流程
- 客户端发起RPC请求到NameNode,请求读取数据
- NameNode收到请求之后,会先校验。如果校验失败,则直接报错;如果校验成功,则NameNode会给客户端返回一个成功信号表示允许读取
- 客户端在收到信号之后,会再次发起请求到NameNode,请求获取第一个Block的位置
- NameNode收到请求之后,会Block的存储位置放到队列中返回给客户端
- 客户端收到队列之后,会将Block的存储位置从队列中全部取出,从中选取一个较近的节点来读取这个Block
- 客户端在读取到Block之后,会对这个Block进行checksum校验(例如Block的大小、内容等)
- 如果校验失败,则客户端会给NameNode发送信号,会从剩余的地址中重新选取位置重新读取重新校验;如果校验成功,那么客户端会向NameNode发送请求,请求获取下一个Block的地址,直到读取完所有的Block
- 当客户端读取完所有的Block之后,会给NameNode发送结束信号。NameNode收到信号之后,会关闭文件
3.3、删除流程
- 客户端发起RPC请求到NameNode,请求删除文件
- NameNode收到请求之后,先进行校验
先校验文件是否存在 - FileNotFoundException
再检验是否有写权限 - AccessControlException:Permission Denied- 如果校验失败,则直接报错;如果校验成功,NameNode会将这个命令记录到edits_inprogress文件中,修改内存中的元数据,修改完成之后,会给客户端返回一个ACK信号。注意:此时文件并没有真正删除而是依然存储在DataNode上
- NameNode等待DataNode的心跳。在收到心跳之后,NameNode会校验心跳,然后在心跳响应中要求DataNode删除对应的Block
- DataNode在收到心跳响应之后,才会删除对应的Block。直到此时,文件才真正从HDFS上移除
四、hadoop 搭建集群
4.1、伪分布式集群搭建
1. 安装JDK1.8
2. 关闭防火墙
service iptables stop
chkconfig iptables off
###如果不能修改主机名,则关闭云主机的初始化服务
service cloud-init stop
service cloud-init-local stop
chkconfig cloud-init off
chkconfig cloud-init-local off
3. 修改主机名 - Hadoop集群中,不建议主机名中出现-或者_
vim /etc/sysconfig/network
修改HOSTNAME属性
HOSTNAME=hadoop01
保存退出,重新生效
source /etc/sysconfig/network
4. 配置IP和主机名的映射
vim /etc/hosts
添加IP 主机名映射,例如
127.0.0.1 localhost localhost.localdomain localhost4 localhost4.localdomain4
::1 localhost localhost.localdomain localhost6 localhost6.localdomain6
10.9.162.133 hadoop01
保存退出
5. 重启
reboot
6. 配置免密互通
产生密钥:ssh-keygen
拷贝公钥:ssh-copy-id root@hadoop01
云主机密码:tarena2017Up;
测试是否成功:ssh root@hadoop01
如果不需要密码:logout
*** 如果出现Name or Service not known或者Unknown host,那么说明IP映射错误
7. 进入/home/software目录
cd /home/software
8. 下载Hadoop安装包
wget http://bj-yzjd.ufile.cn-north-02.ucloud.cn/hadoop-2.7.1_64bit.tar.gz
9. 解压
tar -xvf hadoop-2.7.1_64bit.tar.gz
10. 进入子目录
cd hadoop-2.7.1/etc/hadoop
11. 编辑
vim hadoop-env.sh
修改
export JAVA_HOME=/home/presoftware/jdk1.8
export HADOOP_CONF_DIR=/home/software/hadoop-2.7.1/etc/hadoop/
保存退出,重新生效
source hadoop-env.sh
12. 编辑
vim core-site.xml
添加
<property>
<name>fs.defaultFS</name>
<value>hdfs://hadoop01:9000</value>
</property>
<property>
<name>hadoop.tmp.dir</name>
<value>/home/software/hadoop-2.7.1/tmp</value>
</property>
13. 编辑
vim hdfs-site.xml
添加
<property>
<name>dfs.replication</name>
<value>1</value>
</property>
14. 编辑
cp mapred-site.xml.template mapred-site.xml
vim mapred-site.xml
添加
<property>
<name>mapreduce.framework.name</name>
<value>yarn</value>
</property>
15. 编辑
vim yarn-site.xml
添加
<property>
<name>yarn.resourcemanager.hostname</name>
<value>hadoop01</value>
</property>
<property>
<name>yarn.nodemanager.aux-services</name>
<value>mapreduce_shuffle</value>
</property>
16. 编辑
vim slaves
添加云主机的名字
17. 配置环境变量
vim /etc/profile
在文件末尾追加
export HADOOP_HOME=/home/software/hadoop-2.7.1
export PATH=$PATH:$HADOOP_HOME/bin:$HADOOP_HOME/sbin
保存退出,重新生效
18. Hadoop第一次启动的时候需要进行格式化
hadoop namenode -format
如果出现Storage directory /home/software/hadoop-2.7.1/tmp/dfs/name has been successfully formatted表示格式化成功
***如果出现Command not found:环境变量配置错误或者是配置完环境变量没有source
***如果出现其他错误,那么说明配置文件写错,查找core-site.xml或者是hdfs-site.xml
***如果出现JDK找不到,那么说明hadoop-env.sh配置错误或者没有source
***上述错误修改完成之后,查看/home/software/hadoop-2.7.1目录下是否tmp,如果有tmp目录,修改完错误之后删除这个目录再重新格式化
19. 启动Hadoop
start-all.sh
20. 通过jps查看进程
Jps
NameNode --- 50070
DataNode --- 50075
SecondaryNameNode --- 50090
ResourceManager --- 8088
NodeManager
4.2、完全分布式集群搭建
1. 三台云主机关闭防火墙
2. 三台云主机安装JDK
3. 关闭三台云主机开启初始化
service cloud-init-local stop
service cloud-init stop
chkconfig cloud-init-local off
chkconfig cloud-init off
4. 修改三台云主机的主机名
vim /etc/sysconfig/network
修改HOSTNAME属性
第一台云主机可以改为hadoop01,第二台云主机改为hadoop02,第三台云主机改为hadoop03
改完之后保存退出,重新生效
source /etc/sysconfig/network
5. 三台云主机进行IP映射
vim /etc/hosts
注意,修改完成之后,三台云主机中hosts文件的内容应该一模一样!!!
6. 三台云主机重启
reboot
7. 三台云主机需要相互之间免密
ssh-keygen
ssh-copy-id root@hadoop01
ssh-copy-id root@hadoop02
ssh-copy-id root@hadoop03
云主机密码:tarena2017Up;
ssh hadoop01
如果不需要输入密码,则logout
ssh hadoop02
如果不需要输入密码,则logout
ssh hadoop03
如果不需要输入密码,则logout
8. 先将第一台云主机的Hadoop的伪分布式保留下来
cd /home/software/
mv hadoop-2.7.1/ hadoop-alone
9. 三台云主机都进入software目录,下载配置好的Hadoop分布式安装包
cd /home/software/
wget http://bj-yzjd.ufile.cn-north-02.ucloud.cn/hadoop-dist.tar.gz
10. 解压安装包
tar -xvf hadoop-dist.tar.gz
11. 修改三台云主机的环境变量
vim /etc/profile
在文件末尾添加
export HADOOP_HOME=/home/software/hadoop-2.7.1
export PATH=$PATH:$HADOOP_HOME/bin:$HADOOP_HOME/sbin
保存退出,重新生效
source /etc/profile
12. 三台云主机启动Zookeeper
cd /home/software/zookeeper-3.4.8/bin
sh zkServer.sh start
sh zkServer.sh status
13. 在第一台云主机格式化Zookeeper,实际上就是在Zookeeper上注册Hadoop节点
hdfs zkfc -formatZK
如果出现Successfully created /hadoop-ha/ns in ZK.表示格式化成功
14. 在三台云主机上启动JournalNode
hadoop-daemon.sh start journalnode
15. 在第一台云主机上格式化NameNode
hadoop namenode -format
如果出现 Storage directory /home/software/hadoop-2.7.1/tmp/hdfs/name has been successfully formatted.表示格式化成功
16. 在第一台云主机上启动NameNode
hadoop-daemon.sh start namenode
17. 在第二台云主机上格式化NameNode
hdfs namenode -bootstrapStandby
如果出现Storage directory /home/software/hadoop-2.7.1/tmp/hdfs/name has been successfully formatted.表示格式化成功
18. 在第二台云主机上启动NameNode
hadoop-daemon.sh start namenode
19. 在三台云主机上启动DataNode
hadoop-daemon.sh start datanode
20. 在第一台和第二台云主机上启动FailOverController
hadoop-daemon.sh start zkfc
21. 在第三台云主机上启动YARN
start-yarn.sh
22. 在第一台云主机上启动ResourceManager
yarn-daemon.sh start resourcemanager
通过jps查看
第一个节点会出现8个进程
Jps
NameNode
DataNode
JournalNode
DFSZKFailoverController
ResourceManager
NodeManager
QuorumPeerMain
第二个节点会出现7个进程
Jps
NameNode
DataNode
JournalNode
DFSZKFailoverController
NodeManager
QuorumPeerMain
第三节点会出现6个进程
Jps
DataNode
JournalNode
ResourceManager
NodeManager
QuorumPeerMain
问题解决:
1. Hadoop集群在启动的时候,必须先启动Zookeeper后启动hadoop
2. 如果在上述步骤中,出现Name or Service not Known或者Unknown host,表示IP或者主机名配置错误
3. 如果出现IllegalArgumentException,检查命令是否准确
4. 如果在格式化Zookeeper的时候出现HA is not enable/available,那么表示系统兼容 - 重装云主机系统
5. 如果缺少NameNode/DataNode/JournalNode/DFSZKFailoverController,通过命令hadoop-daemon.sh start namenode/datanode/jounalnode/zkfc。例如hadoop-daemon.sh start datanode
6. 如果缺少了ResourceManager/NodeManager,那么通过yarn-daemon.sh start resourcemanager/nodemanager。例如yarn-daemon.sh start nodemanager
7. 如果在启动过程中出现xxx already running as xxx,但是通过jps又没有发现这个进程,那么通过kill -9 xxx来杀死这个进程,然后重新启动这个进程
8. 如果缺少了QuorumPeerMain,那么说明Zookeeper启动错误
9. 如果出现Command not found,那么表示命令错误或者是环境变量配置错误
10. 如果出现所有命令不生效,那么先从另一台云主机上将profile下载下来,然后上传到有问题的云主机上,替换掉原来的profile,重启云主机
五、hadoop 下载地址
百度云盘链接:https://pan.baidu.com/s/1jCv_dEtussA5Z_4ii40l2Q
(提取码:aj8n
)
(如果提示过期,请评论再次更新)
• 由 ChiKong_Tam 写于 2021 年 1 月 8 日