Zookeeper其二,zk的java和选举机制,Hadoop的高可用和联邦机制

目录

一、Zk是用java代码进行操作(了解)

[使用java代码操作zk 3.5以下版本,使用的技术还是Curator](#使用java代码操作zk 3.5以下版本,使用的技术还是Curator)

二、zk的选举机制

三、Hadoop集群的高可用(HA)

[1) 搭建namenode的高可用](#1) 搭建namenode的高可用)

[Java 代码操作 HA 的 hdfs 代码演示:](#Java 代码操作 HA 的 hdfs 代码演示:)

2)搭建resourcemanager的高可用

四、NameNode的联邦机制【了解】


一、Zk是用java代码进行操作(了解)

复制代码
有很多的软件都是可以使用命令,也可以使用代码进行操作:
MySQL -- SQL语句、使用java代码(JDBC)
HDFS -- shell、Java代码
zookeeper -- shell、Java代码

有两种操作方案:

JDBC 的代码--原生的

DBUtils 工具包

1、原生的API进行操作

2、Curator 工具包进行操作(建议同学们学习这个东西)

第一步:导入Curator工具包

复制代码
<dependency>
  <groupId>org.apache.curator</groupId>
  <artifactId>curator-framework</artifactId>
  <version>4.2.0</version>
</dependency>
<dependency>
  <groupId>org.apache.curator</groupId>
  <artifactId>curator-recipes</artifactId>
  <version>4.2.0</version>
</dependency>
<dependency>
  <groupId>com.google.collections</groupId>
  <artifactId>google-collections</artifactId>
  <version>1.0</version>
</dependency>
<dependency>
  <groupId>junit</groupId>
  <artifactId>junit</artifactId>
  <version>RELEASE</version>
</dependency>
<dependency>
  <groupId>org.slf4j</groupId>
  <artifactId>slf4j-simple</artifactId>
  <version>1.7.25</version>
</dependency>

package com.bigdata;

import org.apache.curator.RetryPolicy;
import org.apache.curator.framework.CuratorFramework;
import org.apache.curator.framework.CuratorFrameworkFactory;
import org.apache.curator.framework.recipes.cache.ChildData;
import org.apache.curator.framework.recipes.cache.TreeCache;
import org.apache.curator.framework.recipes.cache.TreeCacheEvent;
import org.apache.curator.framework.recipes.cache.TreeCacheListener;
import org.apache.curator.retry.ExponentialBackoffRetry;
import org.apache.zookeeper.CreateMode;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;

import java.util.Arrays;
import java.util.List;

public class TestZk {
    CuratorFramework curator =null;
    @Before
    public void init(){
        RetryPolicy retryPolicy = new ExponentialBackoffRetry(1000,2);
        curator = CuratorFrameworkFactory.newClient(
                "bigdata01:2181", retryPolicy
        );
        curator.start();
    }

    @After
    public void destory(){
        curator.close();
    }

    @Test  //
    public void testCreate() throws Exception {
        // 一个类的对象如果是null, 使用null调用任何方法,都报空指针异常
        // 创建一个临时的节点,节点的名字是/hello1
        curator.create().creatingParentContainersIfNeeded().withMode(CreateMode.PERSISTENT).forPath("/xihu/abcd");
        //Thread.sleep(20000);

    }

    @Test  //
    public void testLs() throws Exception {
        // 一个类的对象如果是null, 使用null调用任何方法,都报空指针异常
        // 创建一个临时的节点,节点的名字是/hello1
        //2、查询子节点:ls
        List<String> list = curator.getChildren().forPath("/");
        System.out.println(list);

    }

    @Test  //
    public void testSetData() throws Exception {
        curator.setData().forPath("/xihu/abcd","西湖的水,我的泪".getBytes());
    }

    @Test
    public void testGetData() throws Exception{
        byte[] bytes = curator.getData().forPath("/xihu");
        System.out.println(new String(bytes));
    }

    @Test
    public void testString(){
        // 只学两个东西: 集合(ArrayList HashSet HashMap)   工具类的API (String)   二八原则
        // 想将一个字符串变为byte数组
        String a = "hello";
        byte[] arr = a.getBytes();
        System.out.println(Arrays.toString(arr));
        // 想将一个byte数组变为字符串
        String str = new String(arr);
        System.out.println(str);
    }

    @Test
    public void testDelete() throws Exception{
        curator.delete().forPath("/xihu/abc");
    }

    // 演示watch 监听
    @Test
    public void testWatch() throws Exception{
        TreeCache treeCache = new TreeCache(curator, "/xihu");
        // 一个接口中只有一个未实现的方法,该接口是函数式接口,函数式接口:lambda
        treeCache.getListenable().addListener(new TreeCacheListener() {
            @Override
            public void childEvent(CuratorFramework curatorFramework, TreeCacheEvent treeCacheEvent) throws Exception {
                TreeCacheEvent.Type type = treeCacheEvent.getType();
                ChildData data = treeCacheEvent.getData();
                if(type == TreeCacheEvent.Type.NODE_ADDED){
                    System.out.println("/xihu 下创建了一个新的节点");
                    // data.getData()  如果节点没有数据,返回的是IP;如果节点上有数据,返回的是节点的值
                    System.out.println("该节点上的数据是:"+new String(data.getData()));
                    System.out.println("新增了个路径:"+data.getPath());
                }
                if(type == TreeCacheEvent.Type.NODE_UPDATED){
                    System.out.println("/xihu 下修改了一个节点");
                    // data.getData() 返回的是IP
                    System.out.println("该节点上的数据是:"+new String(data.getData()));
                    System.out.println("修改的路径:"+data.getPath());
                }
                if(type == TreeCacheEvent.Type.NODE_REMOVED){
                    System.out.println("删除了个路径:"+data.getPath());
                }
            }
        });

        treeCache.start();

        Thread.sleep(1000*100);
    }

    @Test
    public void testSwith(){
        String season= "冬";
        switch (season){
            case "冬":
                System.out.println("冬天冷...");
                break;
            case "春":
                System.out.println("春天来了,冬天还会源码?");
                break;
        }
    }

    @Test
    public void testEnum(){
        // WINTER 是枚举类的一个实例化对象
        Season season = Season.WINTER;

        switch (season){
            case WINTER:
                System.out.println("冬天冷...");
                break;
            case SPRING:
                System.out.println("春天来了,冬天还会源码?");
                break;
        }
    }

}

使用java代码操作zk 3.5以下版本,使用的技术还是Curator

第一步:创建项目

第二步:导入包:

复制代码
<!--zk的客户端( curator )-->
<dependency>
    <groupId>org.apache.curator</groupId>
    <artifactId>curator-recipes</artifactId>
    <version>2.7.1</version>
</dependency>

<!--junit测试-->
<dependency>
    <groupId>junit</groupId>
    <artifactId>junit</artifactId>
    <version>4.12</version>
</dependency>

package com.bigdata;

import org.apache.curator.framework.CuratorFramework;
import org.apache.curator.framework.CuratorFrameworkFactory;
import org.apache.curator.framework.recipes.cache.*;
import org.apache.curator.retry.RetryNTimes;
import org.apache.zookeeper.CreateMode;
import org.apache.zookeeper.data.Stat;
import org.junit.Before;
import org.junit.Test;

import java.util.List;

public class TestZk {

    CuratorFramework curator = null;

    @Before
    public void init() {
        // 1. 创建一个连接(自动重连)
        RetryNTimes retry = new RetryNTimes(2, 5);// 重连10次,每次间隔1000秒
        // 2. 创建一个客户端对象。
        curator = CuratorFrameworkFactory.newClient("bigdata01:2181,bigdata02:2181,bigdata03:2181", retry);
        // 3. 启动客户端
        curator.start();
    }

    // 新增节点  永久的
    @Test
    public void testAddNode() throws Exception {
        // 这个里面可以创建四种类型的节点  永久节点 临时节点 永久序列节点 临时序列节点
        String s = curator.create().withMode(CreateMode.PERSISTENT)
        .forPath("/a1", "测试".getBytes());
        System.out.println(s);
    }

    // 获取zk的数据
    @Test
    public void testGetData() throws Exception {
        byte[] bytes = curator.getData().forPath("/a1");
        // byte数组如何变为字符串,使用 String 的构造方法
        System.out.println(new String(bytes));
    }

    // 修改数据
    @Test
    public void testSetData() throws Exception {
        curator.setData().forPath("/a1", "我是打水哥".getBytes());
    }

    // 删除节点
    @Test
    public void testDeleteNode() throws Exception {
        curator.delete().forPath("/a1");
    }

    // 判断一个节点是否存在
    @Test
    public void testIsExists() throws Exception {
        // Stat 表示一个节点信息,如果获取不到节点信息,为null
        Stat stat = curator.checkExists().forPath("/a1");
        System.out.println(stat == null ? "该节点不存在" : "存在");
    }

    // 获取子节点信息,只能获取一层
    @Test
    public void testGetChild() throws Exception {
        List<String> list = curator.getChildren().forPath("/");
        for (String fileName : list) {
            System.out.println(fileName);
        }
    }

    // 给一个节点添加监听器  get /abc watch
    @Test
    public void testSetWatch() throws Exception {
        NodeCache nodeCache = new NodeCache(curator, "/a1");
        nodeCache.start();
        nodeCache.getListenable().addListener(new NodeCacheListener() {
            @Override
            public void nodeChanged() throws Exception {
                byte[] data = nodeCache.getCurrentData().getData();
                System.out.println(new String(data));
            }
        });
        // 这个地方添加这句话的意思是不让程序跑结束,否则一切都白搭了
        Thread.sleep(Integer.MAX_VALUE);
    }


    // 给一个节点的子节点添加监听器  ls /abc watch
    @Test
    public void testSetWatchChild() throws Exception {
        PathChildrenCache cache = new PathChildrenCache(curator, "/a1", true);
        cache.start();
        // 添加监听
        cache.getListenable().addListener(new PathChildrenCacheListener() {
            @Override
            public void childEvent(CuratorFramework client, PathChildrenCacheEvent event) throws Exception {
                                   // 需要知道是新增了还是修改了还是删除了
                                   System.out.println(event.getType());
                                   switch (event.getType()) {
                                   case CHILD_ADDED:
                                   System.out.println("添加了一个节点");
                                   System.out.println(event.getData().getPath());
                                   System.out.println(new String(event.getData().getData()));
                                   break;
                                   case CHILD_UPDATED:
                                   System.out.println("数据更新了");
                                   System.out.println(event.getData().getPath());
                                   System.out.println(new String(event.getData().getData()));
                                   break;
                                   case CHILD_REMOVED:
                                   System.out.println("节点被删除了");
                                   System.out.println(event.getData().getPath());
                                   break;
                                   default:
                                   System.out.println("节点发生了其他变化");
                                   break;
                                   }
                                   }
                                   });

                                   // 这个地方添加这句话的意思是不让程序跑结束,否则一切都白搭了
                                   Thread.sleep(Integer.MAX_VALUE);
                                   }

                                   }

什么是API?

一般是一个技术诞生后,为了方便开发人员通过代码获取其对应的服务,就会开发出来一些方法,开发人员只需要知道调用这个方法有什么效果即可,不需要懂内部的原理,这样的一系列方法就是该技术的API。

什么是接口

接口一般存在于web端,规定只要传递响应的参数,我就完成对应的功能,并且返回结果数据。一般是java工程师和web工程师配合工作时使用,很多开源的技术, 为了方便别人使用,会对外开放很多接口,供开发人员进行调用。

枚举类:

复制代码
package com.bigdata;


// 枚举类
public enum Season {

    SPRING, // Season SPRING = new Season("春");
    SUMMER,
    AUTUMN,
    WINTER;

    // 以下这四个,分别是Season类的四个实例化对象
    Season(String a){

    }

    Season(){

    }
}

枚举类的使用:

复制代码
@Test
    public void testEnum(){
        // WINTER 是枚举类的一个实例化对象
        Season season = Season.WINTER;

        switch (season){
            case WINTER:
                System.out.println("冬天冷...");
                break;
            case SPRING:
                System.out.println("春天来了,冬天还会源码?");
                break;
        }
    }

假如新增节点,报如下错误:当然这个错误也影响结果

main-EventThread\] ERROR org.apache.curator.framework.imps.EnsembleTracker - Invalid config event received: {server.1=bigdata01:2888:3888:participant, version=0, server.3=bigdata03:2888:3888:participant, server.2=bigdata02:2888:3888:participant} \[main-EventThread\] ERROR org.apache.curator.framework.imps.EnsembleTracker - Invalid config event received: {server.1=bigdata01:2888:3888:participant, version=0, server.3=bigdata03:2888:3888:participant, server.2=bigdata02:2888:3888:participant} 请修改 zoo.cfg 配置文件: 老的版本的配置: server.1=bigdata01:2888:3888 server.2=bigdata02:2888:3888 server.3=bigdata03:2888:3888 新的版本的配置: server.1=bigdata01:2888:3888;2181 server.2=bigdata02:2888:3888;2181 server.3=bigdata03:2888:3888;2181 配置完成后,分发一下,然后重启zk集群即可。 ## 二、zk的选举机制 zk中有两种角色:Leader 和 Fllower Leader是自己的集群各台电脑投票选举出来的。 事务:一通操作,要么同时成立,要么都不成立。 举例:Jack 和 Rose Rose 给 Jack(小李子) 转钱 Rose -100 Jack +100 如果中间数据有问题,直接回滚,回复到当初的样子 事务操作:新增,修改,删除等操作 非事务操作: 读数据 但凡跟数据相关的技术,都有事务。 mysql 有事务 jdbc 有事务 mybatis 有事务 zookeeper: Zookeeper 集群工作的核心。 1、事务请求(写操作)的唯一调度和处理者,保证集群事务处理的顺序性; 举例 : 比如添加了一个节点,删除了节点,修改了数据 都是事务操作。 2、集群内部各个服务器的调度者。 3、对于 create, setData, delete 等有写操作的请求,需要统一转发给leader 处理, leader 需要决定编号、执行操作,这个过程称为一个事务。 类似于村长 - 处理客户端非事务(读操作)请求,转发事务请求(写操作)给 Leader; - 参与集群 Leader 选举投票 2n-1台可以做集群投票。 1 3 5 7 9 .... - 此外,针对访问量比较大的 zookeeper 集群, 还可新增观察者角色。 类似于村民 - 观察者角色,观察 Zookeeper 集群的最新状态变化并将这些状态同步过来,其对于非事务请求可以进行独立处理,对于事务请求,则会转发给 Leader服务器进行处理。 - 不会参与任何形式的投票只提供非事务服务,通常用于在不影响集群事务处理能力的前提下提升集群的非事务处理能力。 类似于外来人员(喝汤了) epoch > zxid > myid 先比较 epoch 谁大谁是领导 --资历 逻辑时钟 参与过的选举的次数 类似于老党员。 zxid 如果epoch 相等,就看谁的zxid大,谁就是领导 zxid 代表的是事务的次数 如果这个值很大,就表示这个机器上的数据比较的新 如果zxid 也相等,就看每台电脑上的myid了,如果myid谁大谁是领导。 我现在的集群中,有三台zk,为什么第二台是领导? zk01 1 zk02 2 zk03 3 启动第一台,第一台开始选举,自己投自己一票,因为超过半数才有效,所以zk01不是领导,此时的状态是选举中。 启动第二台,先投自己一票,然后第一台开始投票,比较两者之间谁的myid大,谁的大,就投给谁,zk02再得一票,第二台两票,超过了半数,领导出现了zk02. 启动第三台:发现有领导了,投了吧,当fllower吧。 ## 三、Hadoop集群的高可用(HA) 关于搭建软件的总结:需要拥有三项技能: 1、linux 命令 2、软件的架构以及运行原理 3、会看日志 HA: High Availability,高可用集群,指的是集群7\*24小时不间断服务。 Hadoop中存在单点故障问题:NameNode ResourceManager 问题: NameNode 一个 DataNode 多个 集群中的NameNode挂掉了,整个集群都不可用了。 NameNode存在单点故障。 解决方案:使用zk集群搭建Hadoop的高可用。(NameNode的高可用) 我们可以启动两个NameNode ,其中一台Namenode起作用,另一台备用。 关于集群中的高可用的解决方案: 1、主从模式(冷备) 有一个正常工作,另一个闲置,当第一台服务停掉了,另一台直接顶上。 类似于有两个讲师,一个讲师讲课,另一个讲师在家闲着。 2、双主互备 两个都同时工作,一个挂掉了另一个还可以工作。 两个收银员,一个生病了,另一个继续收银。 3、多节点互备 多个收银员,同时收费(超市结账) ![](https://i-blog.csdnimg.cn/img_convert/a209c0d890dca1838d37f77aa10b04c1.png) 在搭建hadoop集群的高可用之前,先将集群进行快照。 ### 1) 搭建namenode的高可用 先将三台服务器拍摄快照,便于后面的恢复!!! 第一步:bigdata01和bigdata02都能免密登录到其他三台 因为以前bigdata01 已经免密登录其他三台,不需要做。 进入到**bigdata02**中: ssh-keygen -t rsa # 发送公钥(所有NameNode节点都要发送) ssh-copy-id bigdata01 ssh-copy-id bigdata02 ssh-copy-id bigdata03 第二步:三台电脑上都同时安装psmisc # ZKFC远程杀死假死NN使用的killall namenode命令属于该软件中的。 # 建议所有节点都安装psmisc 以下命令是在bigdata01上运行的,因为只有01 配置了xcall命令 xcall.sh yum install -y psmisc 第三步:检查jdk以及zk 三台是否都安装完毕 第四步:检查是否安装了hadoop集群,如果以前安装过了,清空数据 先停止集群:stop-all.sh 清理集群中的data数据: xcall.sh rm -rf /opt/installs/hadoop/tmp/ /opt/installs/hadoop/logs/ 第五步:配置hadoop-env.sh export JAVA_HOME=/opt/installs/jdk/ 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** 修改完毕之后,记得同步给bigdata02和03 xsync.sh hadoop-env.sh 第六步:修改core-site.xml fs.defaultFS hdfs://hdfs-cluster hadoop.tmp.dir /opt/installs/hadoop/tmp ha.zookeeper.quorum bigdata01:2181,bigdata02:2181,bigdata03:2181 第七步:修改hdfs-site.xml dfs.replication 3 dfs.nameservices hdfs-cluster dfs.ha.namenodes.hdfs-cluster nn1,nn2 dfs.namenode.rpc-address.hdfs-cluster.nn1 bigdata01:9820 dfs.namenode.http-address.hdfs-cluster.nn1 bigdata01:9870 dfs.namenode.rpc-address.hdfs-cluster.nn2 bigdata02:9820 dfs.namenode.http-address.hdfs-cluster.nn2 bigdata02:9870 dfs.journalnode.edits.dir /opt/installs/journalnode/data/ dfs.namenode.shared.edits.dir qjournal://bigdata01:8485;bigdata02:8485;bigdata03:8485/hdfs-cluster dfs.ha.automatic-failover.enabled true dfs.client.failover.proxy.provider.hdfs-cluster org.apache.hadoop.hdfs.server.namenode.ha.ConfiguredFailoverProxyProvider dfs.ha.fencing.methods sshfence dfs.ha.fencing.ssh.private-key-files /root/.ssh/id_rsa dfs.webhdfs.enabled true 第八步:检查workers 文件是否为三台服务 第九步:同步 core-site.xml 和 hdfs-site.xml 到剩余两台上去 xsync.sh core-site.xml hdfs-site.xml 第十步: 1、启动zookeeper zk.sh start 2. 初始化ZKFC在zk中的Znode信息【第一次启动需要做】在bigdata01上进行即可 hdfs zkfc -formatZK 3、在三台服务器上启动jn【journalnode 主要用于存储namenode的元数据】 hdfs --daemon start journalnode,否则报8345 这个为什么在这个时候启动,原因是第四步格式化的时候,需要用到journalnode,否则报8485连接超时的问题,格式化会失败的。 4、对集群进行namenode的格式化 hdfs namenode -format 5、启动hdfs start-dfs.sh 这个服务默认会启动journalnode,但是由于你之前已经单独启动过了,所以启动它会报三个警告,可以忽略,无所谓。 6、启动第二个namenode 需要在bigdata02上运行: 第一次需要运行如下命令,以后不需要: hdfs namenode -bootstrapStandby 接着,启动第二个namenode: hadoop-daemon.sh start namenode 本身集群是可以启动两个namenode的,但是由于第一次启动的话,bigdata02上没有格式化,所以无法启动,第二次就不需要了。 综上所述: 只要配置好了以后,以后启动高可用,命令只需要执行 start-dfs.sh 即可。当然zk还是单独管理。 第十一步:通过网页查看两个namenode的状态 ![](https://i-blog.csdnimg.cn/img_convert/6c3f721f88acd55639d0f805bf9ff74e.png) 查看第二个namenode: ![](https://i-blog.csdnimg.cn/img_convert/8b5db66ada344fca9dd022629ded74ae.png) 第十二步:测试是否可以高可用 手动将第一台的namenode给关闭,第二台要自动从 standby变为active ![](https://i-blog.csdnimg.cn/img_convert/088e3554462f0de70c223a30935a3f38.png) 假如第一次服务器再次启动namenode,状态应为为standby ![](https://i-blog.csdnimg.cn/img_convert/e3736c4c330e2b93006e471691715a18.png) #### Java 代码操作 HA 的 hdfs 代码演示: @Test public void testHA() throws Exception{ System.setProperty("HADOOP_USER_NAME","root"); String clusterName = "hdfs-cluster"; String HADOOP_URL = "hdfs://"+clusterName; // 连接hdfs Configuration conf = new Configuration(); conf.set("fs.defaultFS", HADOOP_URL); conf.set("dfs.nameservices", clusterName); conf.set("dfs.ha.namenodes."+clusterName, "nn1,nn2"); conf.set("dfs.namenode.rpc-address."+clusterName+".nn1", "bigdata01:9820"); conf.set("dfs.namenode.rpc-address."+clusterName+".nn2", "bigdata02:9820"); conf.set("dfs.client.failover.proxy.provider."+clusterName, "org.apache.hadoop.hdfs.server.namenode.ha.ConfiguredFailoverProxyProvider"); conf.set("fs.hdfs.impl", "org.apache.hadoop.hdfs.DistributedFileSystem"); //fileSystem = FileSystem.newInstance(new URI("hdfs://bigdata01:9820"),conf); fileSystem = FileSystem.newInstance(new URI("hdfs://hdfs-cluster"),conf); fileSystem.createNewFile(new Path("/newFile.txt")); fileSystem.close(); } ### 2)搭建resourcemanager的高可用 第一步:检查mapred-site.xml ,里面只有yarn配置和historyServer的配置,不需要修改 第二步:修改yarn-site.xml yarn.nodemanager.aux-services mapreduce_shuffle yarn.application.classpath /opt/installs/hadoop/etc/hadoop:/opt/installs/hadoop/share/hadoop/common/lib/*:/opt/installs/hadoop/share/hadoop/common/*:/opt/installs/hadoop/share/hadoop/hdfs:/opt/installs/hadoop/share/hadoop/hdfs/lib/*:/opt/installs/hadoop/share/hadoop/hdfs/*:/opt/installs/hadoop/share/hadoop/mapreduce/*:/opt/installs/hadoop/share/hadoop/yarn:/opt/installs/hadoop/share/hadoop/yarn/lib/*:/opt/installs/hadoop/share/hadoop/yarn/* yarn.log-aggregation-enable true yarn.log-aggregation.retain-seconds 604800 yarn.log.server.url http://bigdata01:19888/jobhistory/logs yarn.resourcemanager.ha.enabled true yarn.resourcemanager.cluster-id yarn-cluster yarn.resourcemanager.ha.rm-ids rm1,rm2 yarn.resourcemanager.hostname.rm1 bigdata01 yarn.resourcemanager.webapp.address.rm1 bigdata01:8088 yarn.resourcemanager.hostname.rm2 bigdata02 yarn.resourcemanager.webapp.address.rm2 bigdata02:8088 yarn.resourcemanager.zk-address bigdata01:2181,bigdata02:2181,bigdata03:2181 yarn.resourcemanager.recovery.enabled true yarn.resourcemanager.store.class org.apache.hadoop.yarn.server.resourcemanager.recovery.ZKRMStateStore yarn.nodemanager.vmem-check-enabled false 以前配置的yarn以及日志服务的配置不动,添加ha的相关配置。 第三步:将mapred-site.xml 和 yarn-site.xml进行同步 [root@bigdata01 ~]# cd /opt/installs/hadoop/etc/hadoop/ [root@bigdata01 hadoop]# xsync.sh yarn-site.xml 只需要同步一个,因为另一个根本没有修改。 第四步:启动yarn start-yarn.sh 如何查看谁是干活的,谁是备用的呢? yarn rmadmin -getAllServiceState 假如你在启动过程中,发现resourcemanager有两个,但是都是standby,有可能是版本兼容问题: hadoop3.1.6 需要兼容 zookeeper 3.4.10 假如你使用的hadoop版本是3.3.1 兼容 zookeeper 3.6.4 ,否则就会有问题。 namenode 高可用没问题,resourcemanager的高可用有问题。 ![](https://i-blog.csdnimg.cn/img_convert/7c3c8f400417c118ffed9f27572f0df3.png) 切换zookeeper集群。 先将以前的zk集群停止。 下载一个对应版本的zk安装包,解压 解压到 /opt/installs 将以前的老的zookeeper 文件夹进行重命名 xcall.sh mv /opt/installs/zookeeper /opt/installs/zookeeper-tmp 将新的zk,进行重命名 为zookeeper 接着分发一下: xsync.sh zookeeper xcall.sh cp /opt/installs/zookeeper-tmp/conf/zoo.cfg /opt/installs/zookeeper/conf 接着在三台服务上创建文件夹: xcall.sh mkdir /opt/installs/zookeeper/zkData 接着将不同电脑上的myid拷贝到相应的zkData里面 xcall.sh cp /opt/installs/zookeeper-tmp/zkData/myid /opt/installs/zookeeper/zkData 启动zk集群: zk.sh start 启动完毕之后,记得格式化一下: hdfs zkfc -formatZK 接着启动start-all.sh 即可 测试一下RM的高可用: \[root@bigdata01 installs\]# yarn rmadmin -getAllServiceState bigdata01:8033 active bigdata02:8033 standby 停止bigdata01中的RM,继续查看: yarn --daemon stop resourcemanager 继续查看: \[root@bigdata01 installs\]# yarn rmadmin -getAllServiceState 2023-08-23 14:40:15,547 INFO ipc.Client: Retrying connect to server: bigdata01/192.168.233.128:8033. Already tried 0 time(s); retry policy is RetryUpToMaximumCountWithFixedSleep(maxRetries=1, sleepTime=1000 MILLISECONDS) bigdata01:8033 Failed to connect: Call From bigdata01/192.168.233.128 to bigdata01:8033 failed on connection exception: java.net.ConnectException: 拒绝连接; For more details see: [http://wiki.apache.org/hadoop/ConnectionRefused](http://wiki.apache.org/hadoop/ConnectionRefused "http://wiki.apache.org/hadoop/ConnectionRefused") bigdata02:8033 active 再次启动bigdata01: \[root@bigdata01 installs\]# yarn rmadmin -getAllServiceState bigdata01:8033 standby bigdata02:8033 active 使用高可用的 yarn 集群,运行一个任务: hadoop jar WordCount01-1.0-SNAPSHOT.jar com.bigdata.WordCountDriver /wc.txt /output3 访问界面:[http://bigdata02:8088/](http://bigdata02:8088/ "http://bigdata02:8088/") 访问 standby 节点,自动跳转到 active 节点的 IP 网站。 ## 四、NameNode的联邦机制【了解】 解决的是:单台namenode节点内存有限的情况。 ![](https://i-blog.csdnimg.cn/img_convert/a9fc140337c19331825755504d6f6781.png) 联邦机制中,可以同时启动多个NameNode,这些namenode 共同组合成了一个集群。 为了防止其中某一台坏掉,导致集群不可用,每一台namenode 都做了高可用(HA). 可靠的方案是: 联邦机制 + HA

相关推荐
Edingbrugh.南空2 小时前
Flink自定义函数
大数据·flink
gaosushexiangji3 小时前
利用sCMOS科学相机测量激光散射强度
大数据·人工智能·数码相机·计算机视觉
无级程序员6 小时前
大数据平台之ranger与ldap集成,同步用户和组
大数据·hadoop
lifallen7 小时前
Paimon 原子提交实现
java·大数据·数据结构·数据库·后端·算法
TDengine (老段)7 小时前
TDengine 数据库建模最佳实践
大数据·数据库·物联网·时序数据库·tdengine·涛思数据
张先shen7 小时前
Elasticsearch RESTful API入门:全文搜索实战(Java版)
java·大数据·elasticsearch·搜索引擎·全文检索·restful
Elastic 中国社区官方博客7 小时前
Elasticsearch 字符串包含子字符串:高级查询技巧
大数据·数据库·elasticsearch·搜索引擎·全文检索·lucene
张先shen8 小时前
Elasticsearch RESTful API入门:全文搜索实战
java·大数据·elasticsearch·搜索引擎·全文检索·restful
天翼云开发者社区9 小时前
Doris-HDFS LOAD常见问题汇总(二)
大数据·doris
简婷187019987759 小时前
源网荷储 + 零碳园区:一场关于能源与未来的双向奔赴
大数据·人工智能·能源