文章目录
零、序
强烈建议看完 Cris 小哥哥的 Linux 学习笔记以及 ZooKeeper 和 Hadoop 的学习笔记再来看这篇笔记,否则你几乎不可能看懂~
1. Hadoop 实现 HA 原理
1.1 什么是 HA?
1)所谓HA(high available),即高可用(7*24小时不中断服务)。
2)实现高可用最关键的策略是消除单点故障(single point of failure,SPOF)。单点故障是一个组件发生故障,就会导致整个系统无法运行。HA严格来说应该分成各个组件的HA机制:HDFS的HA和YARN的HA。
3)Hadoop2.0之前,在HDFS集群中NameNode存在单点故障。
4)NameNode主要在以下两个方面影响HDFS集群
NameNode机器发生意外,如宕机,集群将无法使用,直到管理员重启
NameNode机器需要升级,包括软件、硬件升级,此时集群也将无法使用HDFS HA功能通过配置Active/Standby两个nameNodes实现在集群中对NameNode的热备来解决上述问题。如果出现故障,如机器崩溃或机器需要升级维护,这时可通过此种方式将NameNode很快的切换到另外一台机器
1.2 HA 工作机制
配置两个 namenode
,通过双 namenode
消除单点故障
2. HDFS-HA 手动故障转移(了解)
实际生产中,都是使用自动故障转移,这里给出手动故障转移的操作流程是希望大家知其所以然~
2.1 要点
1)元数据管理方式需要改变:
内存中各自保存一份元数据;
Edits
日志只有 Active
状态的 namenode
节点可以做写操作;
两个 namenode
都可以读取 edits
;
共享的 edits
放在一个共享存储中管理(qjournal
和 NFS
两个主流实现);
2)必须保证两个 NameNode
之间能够 ssh
无密码登录。
3)隔离(Fence),即同一时刻仅仅有一个 NameNode
对外提供服务,防止脑裂(split-brain)
2.2 环境准备
- 修改
IP
- 修改主机名及主机名和
IP
地址的映射 - 关闭防火墙
ssh
免密登录- 安装
JDK
,配置环境变量等
如果不会的同学请参考 Cris 小哥哥的 Hadoop 学习笔记
2.3 测试集群规划
hadoop101 | hadoop102 | hadoop103 | |
---|---|---|---|
HDFS | NameNode DataNode JournalNode | NameNode DataNode JournalNode | DataNode JournalNode |
YARN | NodeManager | ResourceManager NodeManager | NodeManager |
2.4 配置 HDFS-HA 集群
-
首先应该做好虚拟机的快照!!! 防止出现问题随时回滚 ?
-
在
/opt/module/
目录下创建一个HA
文件夹mkdir HA
然后将我们之前就装好的 Hadoop 的文件夹拷贝到 HA 目录里去
cp -r zookeeper-3.4.10/ HA/
-
确保配置
hadoop-env.sh
中的JAVA_HOME
变量为Linux
安装的jdk
目录 -
配置
core-site.xml
,具体配置参数如下<configuration> <!-- 把两个NameNode的地址组装成一个集群mycluster --> <property> <name>fs.defaultFS</name> <value>hdfs://mycluster</value> </property> <!-- 声明journalnode服务本地文件系统存储目录--> <property> <name>dfs.journalnode.edits.dir</name> <value>/opt/module/HA/hadoop-2.7.2/data/jn</value> </property> <!-- 指定hadoop运行时产生文件的存储目录 --> <property> <name>hadoop.tmp.dir</name> <value>/opt/module/HA/hadoop-2.7.2/data/tmp</value> </property> </configuration>
-
配置
hdfs-site.xml
<configuration> <!-- 完全分布式集群名称 --> <property> <name>dfs.nameservices</name> <value>mycluster</value> </property> <!-- 该nameservice下NameNode节点都有哪些 --> <property> <name>dfs.ha.namenodes.mycluster</name> <value>nn1,nn2</value> </property> <!-- nn1的RPC通信地址 --> <property> <name>dfs.namenode.rpc-address.mycluster.nn1</name> <value>hadoop101:8020</value> </property> <!-- nn2的RPC通信地址 --> <property> <name>dfs.namenode.rpc-address.mycluster.nn2</name> <value>hadoop102:8020</value> </property> <!-- nn1的http通信地址 --> <property> <name>dfs.namenode.http-address.mycluster.nn1</name> <value>hadoop101:50070</value> </property> <!-- nn2的http通信地址 --> <property> <name>dfs.namenode.http-address.mycluster.nn2</name> <value>hadoop102:50070</value> </property> <!-- 指定NameNode元数据在JournalNode上的存放位置 --> <property> <name>dfs.namenode.shared.edits.dir</name> <value>qjournal://hadoop101:8485;hadoop102:8485;hadoop103:8485/mycluster</value> </property> <!-- 配置隔离机制,即同一时刻只能有一台服务器对外响应 --> <property> <name>dfs.ha.fencing.methods</name> <value>sshfence</value> </property> <!-- 使用隔离机制时需要ssh无秘钥登录--> <property> <name>dfs.ha.fencing.ssh.private-key-files</name> <value>/home/cris/.ssh/id_rsa</value> </property> <!-- 关闭权限检查--> <property> <name>dfs.permissions.enable</name> <value>false</value> </property> <!-- 客户端访问代理类:客户端通过该类判断哪个namenode是active --> <property> <name>dfs.client.failover.proxy.provider.mycluster</name> <value>org.apache.hadoop.hdfs.server.namenode.ha.ConfiguredFailoverProxyProvider</value> </property> </configuration>
-
接下来所有操作默认是在 /opt/module/HA/hadoop-2.7.2 下进行
-
删除以前的
logs
和data
文件夹rm -rf data/ logs/
如果这两个文件夹不存在就不删
-
分发同步文件到另外的两台机子上
xsync /opt/module/HA/hadoop-2.7.2/
2.5 启动 HDFS-HA 集群
-
接下来所有操作默认是在 /opt/module/HA/hadoop-2.7.2 下进行
-
在各个
JournalNode
节点上,输入以下命令启动journalnode
服务sbin/hadoop-daemon.sh start journalnode
确保三台虚拟机可以正常启动
journalnode
服务 -
在
nn1
上,对其进行格式化,并启动(配置文件设置101
节点为nn1
)bin/hdfs namenode -format sbin/hadoop-daemon.sh start namenode
-
在
nn2
上,同步nn1
的元数据信息bin/hdfs namenode -bootstrapStandby
-
启动
nn2
sbin/hadoop-daemon.sh start namenode
-
观察结果
浏览器打开 http://hadoop102:50070 和 http://hadoop101:50070,可以发现当前
nameNode
服务均为standby
-
在
nn1
上,启动所有datanode
sbin/hadoop-daemons.sh start datanode
-
将
nn2
切换为Active
bin/hdfs haadmin -transitionToActive nn2
-
查看是否
Active
bin/hdfs haadmin -getServiceState nn2
2.6 手动模拟故障并转移
此时我们杀掉 102
上的 nn2
进程,然后手动输入命令指定 101
上的 nn1
进程顶上
这里的 nn2
和 nn1
都是指的 nameNode
进程
kill -9 1982
bin/hdfs haadmin -failover nn2 nn1
可以发现 http://hadoop102:50070 无法访问,但是 http://hadoop101:50070 成为了 active
节点对外提供服务
3. HDFS-HA 自动故障转移(重点)
3.1 原理
前面学习了使用命令hdfs haadmin -failover手动进行故障转移,在该模式下,即使现役NameNode已经失效,系统也不会自动从现役NameNode转移到待机NameNode,下面学习如何配置部署HA自动进行故障转移。
自动故障转移为HDFS部署增加了两个新组件:ZooKeeper和ZKFailoverController(ZKFC)进程。ZooKeeper是维护少量协调数据,通知客户端这些数据的改变和监视客户端故障的高可用服务。
HA的自动故障转移依赖于ZooKeeper的以下功能:1)故障检测:集群中的每个NameNode在ZooKeeper中维护了一个持久会话,如果机器崩溃,ZooKeeper中的会话将终止,ZooKeeper通知另一个NameNode需要触发故障转移。
2)现役NameNode选择:ZooKeeper提供了一个简单的机制用于唯一的选择一个节点为active状态。如果目前现役NameNode崩溃,另一个节点可能从ZooKeeper获得特殊的排外锁以表明它应该成为现役NameNode。
ZKFC是自动故障转移中的另一个新组件,是ZooKeeper的客户端,也监视和管理NameNode的状态。每个运行NameNode的主机也运行了一个ZKFC进程,ZKFC负责:
1)健康监测:ZKFC使用一个健康检查命令定期地ping与之在相同主机的NameNode,只要该NameNode及时地回复健康状态,ZKFC认为该节点是健康的。如果该节点崩溃,冻结或进入不健康状态,健康监测器标识该节点为非健康的。
2)ZooKeeper会话管理:当本地NameNode是健康的,ZKFC保持一个在ZooKeeper中打开的会话。如果本地NameNode处于active状态,ZKFC也保持一个特殊的znode锁,该锁使用了ZooKeeper对短暂节点的支持,如果会话终止,锁节点将自动删除。
3)基于ZooKeeper的选择:如果本地NameNode是健康的,且ZKFC发现没有其它的节点当前持有znode锁,它将为自己获取该锁。如果成功,则它已经赢得了选择,并负责运行故障转移进程以使它的本地NameNode为active。故障转移进程与前面描述的手动故障转移相似,首先杀掉之前active 状态的NameNode,然后本地NameNode转换为active状态。
3.2 原理图
3.3 规划集群
hadoop102 | hadoop103 | hadoop104 | |
---|---|---|---|
HDFS | NameNode DataNode JournalNode ZKFC | NameNode DataNode JournalNode ZKFC | DataNode JournalNode |
YARN | NodeManager | ResourceManager NodeManager | NodeManager |
Zookeeper | Zookeeper | Zookeeper | Zookeeper |
3.4 配置HDFS-HA自动故障转移
注意:确保 ZooKeeper 集群配置完毕以后才能进行这一步操作,详情参考 Cris 的 ZooKeeper 学习笔记
-
具体配置
(1)在
hdfs-site.xml
中增加<property> <name>dfs.ha.automatic-failover.enabled</name> <value>true</value> </property>
(2)在
core-site.xml
文件中增加<property> <name>ha.zookeeper.quorum</name> <value>hadoop101:2181,hadoop102:2181,hadoop103:2181</value> </property>
-
然后使用
xsync
同步修改后的配置文件 -
启动(在
101
服务器),以下操作均在/opt/module/HA/hadoop-2.7.2
下进行(1)关闭所有
HDFS
服务:sbin/stop-dfs.sh
(2)启动
ZooKeeper
集群:startall_zk
这里使用的是
Cris
写的ZooKeeper
群起脚本,详情参考之前笔记,这里不再细说(3)初始化
HA
在Zookeeper
中状态:bin/hdfs zkfc -formatZK
(4)启动
HDFS
服务:sbin/start-dfs.sh
-
此时如果我们使用
kill
杀掉active
状态的nameNode
节点,那么ZooKeeper
将会自动通知standby
状态的nameNode
的ZKFC
,将该台nameNode
节点设置为active
,然后运维人员就开始抢救挂掉的nameNode
节点了~
4. YARN-HA 配置
4.1 YARN-HA工作机制
官方文档:http://hadoop.apache.org/docs/r2.7.2/hadoop-yarn/hadoop-yarn-site/ResourceManagerHA.html
4.2 集群规划
hadoop101 | hadoop102 | hadoop103 | |
---|---|---|---|
HDFS | NameNode DataNode JournalNode ZKFC | NameNode DataNode JournalNode ZKFC | DataNode JournalNode |
YARN | ResourceManager NodeManager | ResourceManager NodeManager | NodeManager |
Zookeeper | Zookeeper | Zookeeper | Zookeeper |
4.3 配置 yarn-site.xml
<configuration>
<property>
<name>yarn.nodemanager.aux-services</name>
<value>mapreduce_shuffle</value>
</property>
<!--启用resourcemanager ha-->
<property>
<name>yarn.resourcemanager.ha.enabled</name>
<value>true</value>
</property>
<!--声明两台resourcemanager的地址-->
<property>
<name>yarn.resourcemanager.cluster-id</name>
<value>cluster-yarn1</value>
</property>
<property>
<name>yarn.resourcemanager.ha.rm-ids</name>
<value>rm1,rm2</value>
</property>
<property>
<name>yarn.resourcemanager.hostname.rm1</name>
<value>hadoop101</value>
</property>
<property>
<name>yarn.resourcemanager.hostname.rm2</name>
<value>hadoop102</value>
</property>
<!--指定zookeeper集群的地址-->
<property>
<name>yarn.resourcemanager.zk-address</name>
<value>hadoop101:2181,hadoop102:2181,hadoop103:2181</value>
</property>
<!--启用自动恢复-->
<property>
<name>yarn.resourcemanager.recovery.enabled</name>
<value>true</value>
</property>
<!--指定resourcemanager的状态信息存储在zookeeper集群-->
<property>
<name>yarn.resourcemanager.store.class</name>
<value>org.apache.hadoop.yarn.server.resourcemanager.recovery.ZKRMStateStore</value>
</property>
<!-- 日志聚集功能使能 -->
<property>
<name>yarn.log-aggregation-enable</name>
<value>true</value>
</property>
<!-- 日志保留时间设置7天 -->
<property>
<name>yarn.log-aggregation.retain-seconds</name>
<value>604800</value>
</property>
</configuration>
然后使用 xsync
同步到其他服务器
4.4 启动yarn
(1)在 hadoop101
中执行:
(2) 在 hadoop102
中执行:
(3)查看服务状态
网页版
可以故意杀掉 101
的 resourcemanager
进程,此时 102
的 resourcemanager
将会自动顶上,感兴趣的可以试试,这里不再赘述
5. HDFS Federation架构设计(了解)
1) NameNode架构的局限性
- Namespace(命名空间)的限制
由于NameNode在内存中存储所有的元数据(metadata),因此单个namenode所能存储的对象(文件+块)数目受到namenode所在JVM的heap size的限制。50G的heap能够存储20亿(200million)个对象,这20亿个对象支持4000个datanode,12PB的存储(假设文件平均大小为40MB)。随着数据的飞速增长,存储的需求也随之增长。单个datanode从4T增长到36T,集群的尺寸增长到8000个datanode。存储的需求从12PB增长到大于100PB。- 隔离问题
由于HDFS仅有一个namenode,无法隔离各个程序,因此HDFS上的一个实验程序就很有可能影响整个HDFS上运行的程序。- 性能的瓶颈
由于是单个namenode的HDFS架构,因此整个HDFS文件系统的吞吐量受限于单个namenode的吞吐量。
2)HDFS Federation架构设计:能不能有多个NameNode?
NameNode NameNode NameNode
元数据 元数据 元数据
Log machine 电商数据/话单数据
简易架构图
3)HDFS Federation应用思考:不同应用可以使用不同NameNode进行数据管理;例如:图片业务、爬虫业务、日志审计业务,而在Hadoop生态系统中,不同的框架使用不同的namenode进行管理namespace(隔离性)