1 High Availability背景知识
1.1 单点故障、高可用
单点故障(英语:single point of failure,缩写 SPOF)是指系统中某一点一旦失效,就会让整个系统无法运作,换句话说,单点故障即会整体故障。
高可用性(英语:high availability,缩写为 HA),IT术语,指系统无中断地执行其功能的能力,代表系统的可用性程度。是进行系统设计时的准则之一。高可用性系统意味着系统服务可以更长时间运行,通常通过提高系统的容错能力来实现。高可用性或者高可靠度的系统不会希望有单点故障造成整体故障的情形。一般可以透过冗余的方式增加多个相同机能的部件,只要这些部件没有同时失效,系统(或
至少部分系统)仍可运作,这会让可靠度提高。
1.2 高可用如何实现
1.2.1 主备集群
解决单点故障,实现系统服务高可用的核心并不是让故障永不发生,而是让故障的发生对业务的影响降到最小。因为软硬件故障是难以避免的问题。当下企业中成熟的做法就是给单点故障的位置设置备份,形成主备架构。通俗描述就是 当 主挂掉 ,备份 顶上,短暂的中断之后继续提供服务。常见的是 一主一备架构,当然也可以一主多备。备份越多,容错能力越强,与此同时,冗余也越大,浪费资源。
1.2.2 Active、Standby
Active:主角色。活跃的角色,代表正在对外提供服务的角色服务。任意时间有且只有一个active对外提供服务。
Standby:备份角色。需要和主角色保持数据、状态同步,并且时刻准备切换成主角色(当主角色挂掉或者出现故障时),对外提供服务,保持服务的可用性。
1.3 可用性评判标准—x个9
在系统的高可用性里有个衡量其可靠性的标准——X X 个9 9,这个X是代表数字3-5。X个9表示在系统1年时间的使用过程中,系统可以正常使用时间与总时间(1年)之比。
➢ 3个 个9:(1-99.9%)36524=8.76小时,表示该系统在连续运行1年时间里最多可能的业务中断时间是8.76小时。
➢ 4个 个9:(1-99.99%)36524=0.876小时=52.6分钟,表示该系统在连续运行1年时间里最多可能的业务中断时间是52.6分钟。
➢ 5个 个9:(1-99.999%)36524*60=5.26分钟,表示该系统在连续运行1年时间里最多可能的业务中断时间是5.26分钟。可以看出,9越多,系统的可靠性越强,能够容忍的业务中断时间越少,但是要付
出的成本更高。
1.4 HA系统设计核心问题
1.4.1 脑裂问题
脑裂(split-brain)是指“大脑分裂”,本是医学名词。在HA集群中,脑裂指的是当联系主备节点的"心跳线"断开时(即两个节点断开联系时),本来为一个整体、动作协调的HA系统,就分裂成为两个独立的节点。由于相互失去了联系,主备节点之间像"
裂脑人"一样,使得整个集群处于混乱状态。脑裂的严重后果:
1) 集群无主:都认为对方是状态好的,自己是备份角色,后果是无服务;
2) 集群多主:都认为对方是故障的,自己是主角色。相互争抢共享资源,结果会
导致系统混乱,数据损坏。此外对于客户端访问也是一头雾水,找谁呢?
避免脑裂问题的核心是:保持任意时刻系统有且只有一个主角色提供服务。
1.4.2 数据同步问题
主备切换保证服务持续可用性的前提是主备节点之间的状态、数据是一致的,或者说准一致的。如果说备用的节点和主节点之间的数据差距过大,即使完成了主备切换的动作,那也是没有意义的。
数据同步常见做法是: 通过日志重演操作记录。主角色正常提供服务,发生的事务性操作通过日志记录,备用角色读取日志重演操作。
2 HDFS NAMENODE单点故障问题
在Hadoop 2.0.0之前, NameNode 是 HDFS 集群中的单点故障( SPOF )。每个群集只
有一个NameNode,如果该计算机或进程不可用,则整个群集在整个NameNode重新启动
或在另一台计算机上启动之前将不可用。
NameNode的单点故障从两个方面影响了HDFS群集的总可用性:
➢ 如果发生意外事件(例如机器崩溃),则在重新启动NameNode之前,群集将不
可用。
➢ 计划内的维护事件,例如NameNode计算机上的软件或硬件升级,将导致群集停
机时间的延长。
HDFS高可用性解决方案:在同一群集中运行两个(从3.0.0起,超过两个)冗余
NameNode。这样可以在机器崩溃的情况下快速故障转移到新的NameNode,或者出于计
划维护的目的由管理员发起的正常故障转移。
3 HDFS HA解决方案—QJM
QJM全称 Quorum Journal Manager,由cloudera公司提出,是Hadoop官方推荐的HDFS
HA解决方案之一。
QJM中,使用zookeeper中ZKFC来实现主备切换;使用Journal Node(JN)集群实
现edits log的共享以达到数据同步的目的。
3.1 QJM—主备切换、脑裂问题解决
3.1.1 ZKFailoverController(zkfc)
Apache ZooKeeper是一款高可用分布式协调服务软件,用于维护少量的协调数据。Zookeeper的下列特性功能参与了HDFS的HA解决方案中:
➢ 临时znode
如果一个znode节点是临时的,那么该znode的生命周期将和创建它的客户端的
session绑定。客户端断开连接session结束,znode将会被自动删除。
➢ Path路径唯一性
zookeeper中维持了一份类似目录树的数据结构。每个节点称之为Znode。Znode具
有唯一性,不会重名。也可以理解为排他性。
➢ 监听机制
客户端可以针对znode上发生的事件设置监听,当事件发生触发条件,zk服务会把
事件通知给设置监听的客户端。
ZKFailoverController(ZKFC)是一个新组件,它是一个ZooKeeper客户端。运行
NameNode的每台计算机也都运行ZKFC,ZKFC的主要职责:
➢ 监视和管理NameNode健康状态
ZKFC通过命令定期ping本地负责监视的NameNode节点。
➢ 维持和ZooKeeper集群联系
如果本地NameNode运行状况良好,并且ZKFC看到当前没有其他节点持有锁znode,
它将自己尝试获取该锁。如果成功,则表明它“赢得了选举”,并负责运行故障转
移以使其本地NameNode处于Active状态。如果已经有其他节点持有锁,zkfc选举失
败,则会对该节点注册监听,等待下次继续选举。
3.1.2 Fencing隔离机制
故障转移过程也就是俗称的主备角色切换的过程,切换过程中最怕的就是脑裂的
发送。因此需要 Fencing 机制来避免,将先前的Active节点隔离,然后将本地NameNode
转换为Active状态。
Hadoop公共库中对外提供了两种fenching实现,分别是sshfence和shellfence(缺
省实现),其中sshfence是指通过ssh登陆目标节点上,使用命令fuser将进程杀死(通
过tcp端口号定位进程pid,该方法比jps命令更准确),shellfence是指执行一个用户
事先定义的shell命令(脚本)完成隔离。
5.3.2 QJM—主备数据同步问题解决
Journal Node ( JN ) 集群是轻量级分布式系统,主要用于高速读写数据、存储数
据。通常使用 2N+1台JournalNode存储共享Edits Log(编辑日志)。
任何修改操作在 Active NN上执行时,JournalNode进程同时也会记录edits log
到 至少半数以上的JN中,这时 Standby NN 监测到JN 里面的同步log发生变化了会读
取JN里面的edits log,然后重演操作记录同步到自己的目录镜像树里面,
当发生故障Active NN挂掉后,Standby NN 会在它成为Active NN 前,读取所有
的JN里面的修改日志,这样就能高可靠的保证与挂掉的NN的目录镜像树一致,然后无
缝的接替它的职责,维护来自客户端请求,从而达到一个高可用的目的。
4 HDFS HA环境搭建
HA集群搭建的难度主要在于配置文件的编写!
4.1 集群基础环境准备
1.修改Linux主机名 /etc/hostname
2.修改IP /etc/sysconfig/network-scripts/ifcfg-ens33
3.修改主机名和IP的映射关系 /etc/hosts
4.关闭防火墙
5.ssh免登陆
6.安装JDK,配置环境变量等 /etc/profile
7.集群时间同步
8.配置主备NN之间的互相免密登录
4.2 HA集群规划
node1 namenode zkfc datanode zookeeper journal node node2 namenode zkfc datanode zookeeper journal node node3 datanode zookeeper journal node
4.3 上传解压Hadoop安装包
hadoop-3.1.4-bin-snappy-CentOS7.tar.gz
tar zxvf hadoop-3.1.4-bin-snappy-CentOS7.tar.gz -C /export/server/
4.4 配置Hadoop环境变量
export HADOOP_HOME=/export/server/hadoop-3.1.4
export PATH=P A T H : PATH:PATH:HADOOP_HOME/bin:$HADOOP_HOME/sbin
4.5 修改Hadoop配置文件
4.5.1 hadoop-env.sh
cd /export/server/hadoop-3.1.4/etc/Hadoop vim hadoop-env.sh export JAVA_HOME=/export/server/jdk1.8.0_65 export HDFS_NAMENODE_USER=root export HDFS_DATANODE_USER=root export HDFS_JOURNALNODE_USER=root export HDFS_ZKFC_USER=root
4.5.2 core-site.xml
vim core-site.xml
<configuration> <!-- HA集群名称,该值要和hdfs-site.xml中的配置保持一致 --> <property> <name>fs.defaultFS</name> <value>hdfs://mycluster</value> </property> <!-- hadoop本地磁盘存放数据的公共目录 --> <property> <name>hadoop.tmp.dir</name> <value>/export/data/ha-hadoop</value> </property> <!-- ZooKeeper集群的地址和端口--> <property> <name>ha.zookeeper.quorum</name> <value>node1.itcast.cn:2181,node2.itcast.cn:2181,node3.itcast.cn:2181</value> </property> </configuration>
4.5.3 hdfs-site.xml
<configuration> <!--指定hdfs的nameservice为mycluster,需要和core-site.xml中的保持一致 --> <property> <name>dfs.nameservices</name> <value>mycluster</value> </property> <!-- mycluster下面有两个NameNode,分别是nn1,nn2 --> <property> <name>dfs.ha.namenodes.mycluster</name> <value>nn1,nn2</value> </property> <!-- nn1的RPC通信地址 --> <property> <name>dfs.namenode.rpc-address.mycluster.nn1</name> <value>node1.itcast.cn:8020</value> </property> <!-- nn1的http通信地址 --> <property> <name>dfs.namenode.http-address.mycluster.nn1</name> <value>node1.itcast.cn:9870</value> </property> <!-- nn2的RPC通信地址 --> <property> <name>dfs.namenode.rpc-address.mycluster.nn2</name> <value>node2.itcast.cn:8020</value> </property> <!-- nn2的http通信地址 --> <property> <name>dfs.namenode.http-address.mycluster.nn2</name> <value>node2.itcast.cn:9870</value> </property> <!-- 指定NameNode的edits元数据在JournalNode上的存放位置 --> <property> <name>dfs.namenode.shared.edits.dir</name> <value>qjournal://node1.itcast.cn:8485;node2.itcast.cn:8485;node3.itcast.cn:8485/myclust er</value> </property> <!-- 指定JournalNode在本地磁盘存放数据的位置 --> <property> <name>dfs.journalnode.edits.dir</name> <value>/export/data/journaldata</value> </property> <!-- 开启NameNode失败自动切换 --> <property> <name>dfs.ha.automatic-failover.enabled</name> <value>true</value> </property> <!-- 指定该集群出故障时,哪个实现类负责执行故障切换 --> <property> <name>dfs.client.failover.proxy.provider.mycluster</name> <value>org.apache.hadoop.hdfs.server.namenode.ha.ConfiguredFailoverProxyProvider</value > </property> <!-- 配置隔离机制方法--> <property> <name>dfs.ha.fencing.methods</name> <value>sshfence</value> </property> <!-- 使用sshfence隔离机制时需要ssh免登陆 --> <property> <name>dfs.ha.fencing.ssh.private-key-files</name> <value>/root/.ssh/id_rsa</value> </property> <!-- 配置sshfence隔离机制超时时间 --> <property> <name>dfs.ha.fencing.ssh.connect-timeout</name> <value>30000</value> </property> </configuration>
4.5.4 workers
node1.itcast.cn
node2.itcast.cn
node3.itcast.cn
4.6 集群同步安装包
在node1上:
cd /export/server
scp -r hadoop-3.1.4 root@node2:$PWD scp -r hadoop-3.1.4 root@node3:$PWD
4.7 HA集群初始化
4.7.1 启动zk集群
/export/server/zookeeper-3.4.6/bin/zkServer.sh start
4.7.2 手动启动JN集群
hdfs --daemon start journalnode
4.7.3 Format namenode
在node1执行格式化namenode
hdfs namenode -format
在node1启动namenode进程
hdfs --daemon start namenode
在node2上进行namenode元数据同步
hdfs namenode -bootstrapStandby
4.7.4 格式化zkfc
注意,在哪台机器上执行,哪台机器就将成为第一次的Active NN
hdfs zkfc –formatZK
4.8 HA集群启动
在node1上启动HDFS集群
5 HDFS HA效果演示
在node1上,显示namenode是active状态
在node2上,显示namenode是standby状态
5.1 正常操作
Node2无法浏览,想一想为什么?
5.2 模拟故障出现
在node1,手动kill杀死namenode进程。
此时发现node2上的namenode切换成为Active状态 hdfs服务正常可用。
5.3 HA切换失败—错误解决
使用kill -9模拟JVM崩溃。或者重新启动计算机电源或拔出其网络接口以模拟另一种故障。另一个NameNode应在几秒钟内自动变为活动状态。检测故障并触发故障转
移所需的时间取决于ha.zookeeper.session-timeout.ms的配置,但默认值为5秒。如果测试不成功,检查 zkfc 守护程序以及 NameNode 守护程序的日志,以便进一步
诊断问题。如果错误信息如下:
提示未找到fuser程序,导致无法进行fence,所以可以通过如下命令来安装,
Psmisc软件包中包含了fuser程序(两个NN机器上都需要进行安装)
yum install psmisc -y