一. High Availability背景常识

1. 单点故障、高可用

单点故障(英语:single point of failure,缩写SPOF)是指零碎中某一点一旦生效,就会让整个零碎无奈运作,换句话说,单点故障即会整体故障

高可用性(英语:high availability,缩写为 HA),IT术语,指零碎无中断地执行其性能的能力,代表零碎的可用性水平。是进行零碎设计时的准则之一。高可用性零碎意味着零碎服务能够更长时间运行,通常通过进步零碎的容错能力来实现

高可用性或者高牢靠度的零碎不会心愿有单点故障造成整体故障的情景。个别能够透过冗余的形式减少多个雷同机能的部件,只有这些部件没有同时生效,零碎(或至多局部零碎)仍可运作,这会让牢靠度提高。

2. 高可用的实现

  1. 主备集群
    解决单点故障,实现零碎服务高可用的外围并不是让故障永不产生,而是让故障的产生对业务的影响降到最小。因为软硬件故障是难以避免的问题。
    当下企业中成熟的做法就是给单点故障的地位设置备份,造成主备架构。艰深形容就是当主挂掉,备份顶上,短暂的中断之后持续提供服务。
    常见的是一主一备架构,当然也能够一主多备。备份越多,容错能力越强,与此同时,冗余也越大,浪费资源。
  2. Active、Standby
    Active:主角色。沉闷的角色,代表正在对外提供服务的角色服务。任意工夫有且只有一个active对外提供服务。
    Standby:备份角色。须要和主角色保持数据、状态同步,并且时刻筹备切换成主角色(当主角色挂掉或者呈现故障时),对外提供服务,放弃服务的可用性。

3. 可用性评判规范—x个9

在零碎的高可用性里有个掂量其可靠性的规范——X个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越多,零碎的可靠性越强,可能容忍的业务中断工夫越少,然而要付出的老本更高

4. HA 零碎设计外围问题

  1. 脑裂问题

脑裂(split-brain)是指“大脑决裂”,本是医学名词。在HA集群中,脑裂指的是当分割主备节点的"心跳线"断开时(即两个节点断开分割时),原本为一个整体、动作协调的HA零碎,就决裂成为两个独立的节点。因为互相失去了分割,主备节点之间像"裂脑人"一样,使得整个集群处于混乱状态。脑裂的严重后果:

  • 集群无主:都认为对方是状态好的,本人是备份角色,结果是无服务;
  • 集群多主:都认为对方是故障的,本人是主角色。互相争抢共享资源,后果会导致系统凌乱,数据损坏。此外对于客户端拜访也是一头雾水,找谁呢?

防止脑裂问题的外围是:放弃任意时刻零碎有且只有一个主角色提供服务

  1. 数据同步问题
    主备切换保障服务继续可用性的前提是主备节点之间的状态、数据是统一的,或者说准统一的。如果说备用的节点和主节点之间的数据差距过大,即便实现了主备切换的动作,那也是没有意义的。
    数据同步常见做法是:通过日志重演操作记录。主角色失常提供服务,产生的事务性操作通过日志记录,备用角色读取日志重演操作。

    二. HDFS NAMENODE单点故障问题

    在Hadoop 2.0.0之前,NameNode是HDFS集群中的单点故障(SPOF)。每个群集只有一个NameNode,如果该计算机或过程不可用,则整个群集在整个NameNode重新启动或在另一台计算机上启动之前将不可用。
    NameNode的单点故障从两个方面影响了HDFS群集的总可用性

    • 如果产生意外事件(例如机器解体),则在重新启动NameNode之前,群集将不可用。
    • 打算内的保护事件,例如NameNode计算机上的软件或硬件降级,将导致群集停机工夫的缩短。

    HDFS高可用性解决方案:在同一群集中运行两个(从3.0.0起,超过两个)冗余NameNode。这样能够在机器解体的状况下疾速故障转移到新的NameNode,或者出于打算保护的目标由管理员发动的失常故障转移。
    单点部署:

    高可用部署

三. HDFS HA解决方案—QJM

QJM全称Quorum Journal Manager,由cloudera公司提出,是Hadoop官网举荐的HDFS HA解决方案之一
QJM中,应用zookeeper中ZKFC来实现主备切换;应用Journal Node(JN)集群实现edits log的共享以达到数据同步的目标。

1. QJM—主备切换、脑裂问题解决

  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选举失败,则会对该节点注册监听,期待下次持续选举。
  2. Fencing 隔离机智
    故障转移过程也就是俗称的主备角色切换的过程,切换过程中最怕的就是脑裂的发送。因而须要Fencing机制来防止,将先前的Active节点隔离,而后将本地NameNode转换为Active状态
    Hadoop公共库中对外提供了两种fenching实现,别离是sshfence和shellfence(缺省实现),其中sshfence是指通过ssh登陆指标节点上,应用命令fuser将过程杀死(通过tcp端口号定位过程pid,该办法比jps命令更精确),shellfence是指执行一个用户当时定义的shell命令(脚本)实现隔离。

    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. HA环境搭建

HA集群搭建的难度次要在于配置文件的编写,心细,心细,心细!

1. 集群根底环境筹备

  1. 批改Linux 主机名 /etc/hostname
  2. 批改IP /etc/sysconfig/network-scripts/ifcfg-ens33
  3. 批改主机名和Ip映射关系
  4. 敞开防火墙
  5. ssh免密登陆
  6. 装置JDK,配置环境变量等 /etc/profile
  7. 集群工夫同步
  8. 配置主备NN之间的互相免密登录

2. HA集群布局

node1  namenode  zkfc   datanode   zookeeper   journal nodenode2  namenode  zkfc   datanode   zookeeper   journal nodenode3  datanode zookeeper journal node9

3. 装置配置zookeepe

上传zookeeper 至linux

  1. 解压

    tar -zxvf zookeeper-3.4.5.tar.gz -C /export/server
  2. 批改配置文件

             cd /export/server/zookeeper-3.4.5/conf/         cp zoo_sample.cfg zoo.cfg         vim zoo.cfg         批改:dataDir=/export/data/zkdata         在最初增加:         server.1=node1:2888:3888         server.2=node2:2888:3888         server.3=node3:2888:3888         保留退出         而后创立一个tmp文件夹         mkdir /export/data/zkdata         echo 1 > /export/data/zkdata/myid
  3. 将配置好的zookeeper拷贝到其余节点

             scp -r /export/server/zookeeper-3.4.5 node2:/export/server         scp -r /export/server/zookeeper-3.4.5 node3:/export/server                  编辑node2、node3对应/export/data/zkdata/myid内容         node2:             mkdir /export/data/zkdata             echo 2 > /export/data/zkdata/myid         node3:             mkdir /export/data/zkdata             echo 3 > /export/data/zkdata/myid

4. 上传解压Hadoop安装包

hadoop-3.1.4-bin-snappy-CentOS7.tar.gztar zxvf hadoop-3.1.4-bin-snappy-CentOS7.tar.gz -C /export/server/

5.配置Hadoop 环境变量

vim /etc/profileexport HADOOP_HOME=/export/server/hadoop-3.1.4export PATH=$PATH:$HADOOP_HOME/bin:$HADOOP_HOME/sbinsource /etc/profile

6. 批改Hadoop 配置文件

  1. hadoop-env.sh

    cd /export/server/hadoop-3.1.4/etc/Hadoopvim hadoop-env.shexport JAVA_HOME=/export/server/jdk1.8.0_65export HDFS_NAMENODE_USER=rootexport HDFS_DATANODE_USER=rootexport HDFS_JOURNALNODE_USER=rootexport HDFS_ZKFC_USER=root
  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>
  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/mycluster</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>
  1. workers

    # 每台服务器的主机名:node1.uuicon.cnnode2.uuicon.cnnode3.uuicon.cn
  2. 批改mapred-site.xml

    <configuration><!-- 指定mr框架为yarn形式 --><property><name>mapreduce.framework.name</name><value>yarn</value></property></configuration>    

    7.配置免明码登陆

    配置参考教程

    1. 首先要配置node1到node1、node2、node3的免明码登陆
      2. 两个namenode之间要配置ssh免明码登陆 ssh近程补刀时候须要

    8. 集群同步安装包

    cd /export/serverscp -r hadoop-3.1.4 root@node2:$PWDscp -r hadoop-3.1.4 root@node3:$PWD

    5. 启动HA-Hadoop 集群

    1. 启动zookeeper集群 (别离在node1、node2、node3上启动zk)

    bin/zkServer.sh start#查看状态:一个leader,两个followerbin/zkServer.sh status

    2. 手动启动journalnode(别离在在node1、node2、node3上执行)

    hadoop-daemon.sh start journalnode#运行jps命令测验,多了JournalNode过程

    3. 格式化namenode

    #在node1上执行命令:hdfs namenode -format#格式化后会在依据core-site.xml中的hadoop.tmp.dir配置的目录下生成个hdfs初始化文件,#在node1启动namenode过程hdfs --daemon start namenode##在node2上进行元数据同步hdfs namenode -bootstrapStandby

    4. 格式化ZKFC(在active上执行即可)

    hdfs zkfc -formatZK

    5. 启动HDFS(在node1上执行)

    start-dfs.sh

    6. 启动YARN

    start-yarn.sh还须要手动在standby上手动启动备份的  resourcemanageryarn-daemon.sh start resourcemanager