Hadoop高可用集群搭建

一、HDFS HA简介

1.1 QJM简介

1.Quorum Journal Manager(仲裁日志管理器),是Hadoop官方推荐的HDFS HA解决方案之一
2.使用zookeeper中ZKFC来实现主备切换;
3.使用Journal Node(JN)集群实现edits log的共享以达到数据同步的目的

1.2 主备切换问题解决方案--ZKFailoverController(zkfc)

ZK Failover Controller(ZKFC)是一个ZooKeeper客户端。主要职责:
    1.监视和管理NameNode健康状态
    2.ZKFC通过命令监视的NameNode节点及机器的健康状态。
    3.维持和ZK集群联系
            如果本地NameNode运行状况良好,并且ZKFC看到当前没有其他节点持有锁znode,它将自己尝试获取该锁。如果成功,则表明它“赢得了选举”,并负责运行故障转移以使其本地NameNode处于Active状态。如果已经有其他节点持有锁,zkfc选举失败,则会对该节点注册监听,等待下次继续选举。

1.3 主备脑裂问题解决方案-Fencing(隔离)机制

故障转移过程也就是俗称的主备角色切换的过程,切换过程中最怕的就是脑裂的发生。因此需要Fencing机制来避免,将先前的Active节点隔离,然后将Standby转换为Active状态。
Hadoop公共库中对外提供了两种Fenching实现,分别是sshfence和shellfence(缺省实现)。
sshfence是指通过ssh登陆目标节点上,使用命令fuser将进程杀死(通过tcp端口号定位进程pid,该方法比jps命令更准确);
shellfence是指执行一个用户事先定义的shell命令(脚本)完成隔离。

1.4 主备数据状态同步问题解决

Journal Node(JN)集群是轻量级分布式系统,主要用于高速读写数据、存储数据。
通常使用2N+1台JournalNode存储共享Edits Log(编辑日志)。--底层类似于zk的分布式一致性算法。
任何修改操作在 Active NN上执行时,JournalNode进程同时也会记录edits log到至少半数以上的JN中,这时 Standby NN 监测到JN 里面的同步log发生变化了会读取JN里面的edits log,然后重演操作记录同步到自己的目录镜像树里面。

二、集群角色规划及基础环境要求

角色规划

基础环境要求

1.修改Linux主机名        
2.修改IP                 
3.修改主机名和IP的映射关系 
4.关闭防火墙
5.ssh免登陆
6.安装JDK,配置环境变量等  
7.集群时间同步
8.配置主备NN之间的互相免密登录
9.安装fuser nc命令,Fence状态检测时需要  #yum install nc psmisc -y

三、安装配置Hadoop

此篇文档及Hadoop相关文档相关软件包统一在此百度网盘:

链接:https://pan.baidu.com/s/11F4THdIfgrULMn2gNcObRA?pwd=cjll

3.1 解压及创建软链接

tar xf hadoop-3.1.4-bin-snappy-CentOS7.tar.gz -C /usr/local/
cd /usr/local/
ln -sv hadoop-3.1.4 hadoop

3.2 全局环境变量配置

vim /etc/profile.d/hadoop.sh
export HADOOP_HOME=/usr/local/hadoop
export PATH=$PATH:$HADOOP_HOME/bin:$HADOOP_HOME/sbin

. /etc/profile.d/hadoop.sh

3.3 修改hadoop-env.sh文件,设置运行环境变量及运行用户

export JAVA_HOME=/usr/local/java
export HDFS_NAMENODE_USER=root
export HDFS_DATANODE_USER=root
export HDFS_SECONDARYNAMENODE_USER=root
export YARN_RESOURCEMANAGER_USER=root
export YARN_NODEMANAGER_USER=root
export HDFS_JOURNALNODE_USER=root
export HDFS_ZKFC_USER=root

3.4 修改core-site.xml

主要注意A集群名称要和hdfs-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>/Hadoop/ha-hadoop</value>
    </property>
    <!-- 设置HDFS web UI访问用户 -->
    <property>
        <name>hadoop.http.staticuser.user</name>
        <value>root</value>
    </property>
    <!-- ZooKeeper集群的地址和端口-->
    <property>
        <name>ha.zookeeper.quorum</name>
        <value>hdp01.dialev.com:2181,hdp02.dialev.com:2181,hdp03.dialev.com:2181</value>
    </property>
</configuration>

3.5 修改hdfs-site.xml

主要注意集群名称和core-site中保持一致,集群相关节点及属性name cluster名称记得替换,再一次检查节点之间是否可以免密登录

<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>hdp01.dialev.com:8020</value>
        </property>

        <!-- nn1的http通信地址 -->
        <property>
                <name>dfs.namenode.http-address.mycluster.nn1</name>
                <value>hdp01.dialev.com:9870</value>
        </property>

        <!-- nn2的RPC通信地址 -->
        <property>
                <name>dfs.namenode.rpc-address.mycluster.nn2</name>
                <value>hdp02.dialev.com:8020</value>
        </property>
        
        <!-- nn2的http通信地址 -->
        <property>
                <name>dfs.namenode.http-address.mycluster.nn2</name>
                <value>hdp02.dialev.com:9870</value>
        </property>

        <!-- 指定NameNode的edits元数据在JournalNode上的存放位置 -->
        <property>
                <name>dfs.namenode.shared.edits.dir</name>
                <value>qjournal://hdp01.dialev.com:8485;hdp02.dialev.com:8485;hdp03.dialev.com:8485/mycluster</value>
        </property>

        <!-- 指定JournalNode在本地磁盘存放数据的位置 生产环境应当和数据盘分开-->
        <property>
                <name>dfs.journalnode.edits.dir</name>
                <value>/Hadoop/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>

3.6 修改mapred-site.xml

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

3.7 修改 yarn-site.xml

<configuration>
  <!-- 开启RM高可用 -->
  <property>
    <name>yarn.resourcemanager.ha.enabled</name>
    <value>true</value>
  </property>

  <!-- 指定RM的cluster id -->
  <property>
    <name>yarn.resourcemanager.cluster-id</name>
    <value>yrc</value>
  </property>

  <!-- 指定RM的名字 -->
  <property>
    <name>yarn.resourcemanager.ha.rm-ids</name>
    <value>rm1,rm2</value>
  </property>

  <!-- 分别指定RM的地址 -->
  <property>
    <name>yarn.resourcemanager.hostname.rm1</name>
    <value>hdp01.dialev.com</value>
  </property>
  <property>
    <name>yarn.resourcemanager.hostname.rm2</name>
    <value>hdp02.dialev.com</value>
  </property>

  <!-- 指定zk集群地址 -->
  <property>
    <name>yarn.resourcemanager.zk-address</name>
    <value>hdp01.dialev.com:2181,hdp02.dialev.com,hdp03.dialev.com:2181</value>
  </property>

  <property>
    <name>yarn.nodemanager.aux-services</name>
    <value>mapreduce_shuffle</value>
  </property>
  </configuration>

3.8 修改workers

hdp01.dialev.com
hdp02.dialev.com
hdp03.dialev.com

3.9 同步配置到其他节点

scp -r hadoop-3.1.4 192.168.1.132:/usr/local/
scp -r hadoop-3.1.4 192.168.1.133:/usr/local/

#其他节点做好软连接
cd /usr/local/
 ln -sv hadoop-3.1.4 hadoop

四、启动服务

4.1 启动ZK

参考此文档部署,不再赘述:https://www.cnblogs.com/panwenbin-logs/p/10369402.html

4.2 启动journalnode 

# 在每一个节点上执行
hadoop-daemon.sh start journalnode
jps #运行jps命令检验,多了JournalNode进程

4.3 格式namenode

#在hdp01上执行命令:
hdfs namenode -format
#格式化后会在根据core-site.xml中的hadoop.tmp.dir配置的目录下生成个hdfs初始化文件,

#在hdp01启动namenode进程
hdfs --daemon start namenode

4.4 hdp02进行元数据同步

#在hdp02上进行元数据同步
hdfs namenode -bootstrapStandby

4.5 格式化ZKFC

# namenode首次选举需要用户指定,下面命令在哪个节点执行,哪个节点就是active,当前我们在hdp01即可

hdfs zkfc -formatZK

4.6 启动 HDFS

# 在hdp01上执行
start-dfs.sh

4.7 启动

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

五、集群验证

5.1 浏览器访问namenode web界面

可以看到节点1当前状态为active,节点2为standby

 

5.2 查看集群操作是否正常

hdfs dfsadmin -report
hadoop fs -mkdir /test01
hadoop fs -put workers /test01
hadoop fs -ls /test01

5.3 验证namenode工作状态

namenode主备之间同时只能有一个主对外提供服务即active可以操作,standby不可以操作

节点2报错

5.4 验证namenode故障转移

# 杀死namenode active节点进程
[root@hdp01 hadoop]# jps |grep -i namenode
50305 NameNode
[root@hdp01 hadoop]# kill 50305

节点1浏览器无法打开,查看节点2,可以看到节点2切换到active

 数据也可以正常浏览

如果未正常切换可以查看节点hadoop-root-zkfc-{node_name}.log日志报错

5.5 查看namenode恢复集群状态

hdfs --daemon start namenode

查看节点1状态,自动切换为standby

 

 

 

 

  

 
posted @ 2023-02-27 11:51  百衲本  阅读(402)  评论(0编辑  收藏  举报
cnblogs_post_body { color: black; font: 0.875em/1.5em "微软雅黑" , "PTSans" , "Arial" ,sans-serif; font-size: 15px; } cnblogs_post_body h1 { text-align:center; background: #333366; border-radius: 6px 6px 6px 6px; box-shadow: 0 0 0 1px #5F5A4B, 1px 1px 6px 1px rgba(10, 10, 0, 0.5); color: #FFFFFF; font-family: "微软雅黑" , "宋体" , "黑体" ,Arial; font-size: 23px; font-weight: bold; height: 25px; line-height: 25px; margin: 18px 0 !important; padding: 8px 0 5px 5px; text-shadow: 2px 2px 3px #222222; } cnblogs_post_body h2 { text-align:center; background: #006699; border-radius: 6px 6px 6px 6px; box-shadow: 0 0 0 1px #5F5A4B, 1px 1px 6px 1px rgba(10, 10, 0, 0.5); color: #FFFFFF; font-family: "微软雅黑" , "宋体" , "黑体" ,Arial; font-size: 20px; font-weight: bold; height: 25px; line-height: 25px; margin: 18px 0 !important; padding: 8px 0 5px 5px; text-shadow: 2px 2px 3px #222222; } cnblogs_post_body h3 { background: #2B6695; border-radius: 6px 6px 6px 6px; box-shadow: 0 0 0 1px #5F5A4B, 1px 1px 6px 1px rgba(10, 10, 0, 0.5); color: #FFFFFF; font-family: "微软雅黑" , "宋体" , "黑体" ,Arial; font-size: 18px; font-weight: bold; height: 25px; line-height: 25px; margin: 18px 0 !important; padding: 8px 0 5px 5px; text-shadow: 2px 2px 3px #222222; } 回到顶部 博客侧边栏 回到顶部 页首代码 回到顶部 页脚代码