zoukankan      html  css  js  c++  java
  • Hadoop高可用集群

    Hadoop高可用集群

    由于一个HDFS集群由一个NameNode节点和多个DataNode节点组成,一旦NameNode节点宕机,那么HDFS将不能进行文件的上传与下载。 

    由于一个Yarn集群由一个ResourceManager节点和多个NodeManager节点组成,一旦ResourceManager节点宕机,那么YARN集群将不能进行资源的调度。

    Hadoop各个模块剖析:https://www.cnblogs.com/funyoung/p/9889719.html

    Hadoop集群管理:https://www.cnblogs.com/funyoung/p/9920828.html

     

    1.搭建HDFS的高可用集群

    由于一个HDFS集群由一个NameNode节点和多个DataNode节点组成,一旦NameNode节点宕机,那么HDFS将不能进行文件的上传与下载。

    Hadoop依赖Zookeeper实现HDFS集群的高可用,由状态为Active的NameNode节点对外提供服务,而状态为StandBy的NameNode节点则负责数据的同步,一旦状态为Active的NameNode节点宕机,则状态为StandBy的NameNode节点将会切换为Active状态对外提供服务。

     

     

     

     

     

     

     

     

     

     

     

     

     

    Hadoop提供了NameService进程,其是NameNode的代理,客户端直接访问的是NameService,NameService会将请求转发给状态为Active的NameNode。

    当启动HDFS时,DataNode节点会同时向两个NameNode节点进行注册。

     

    关于NameService如何进行状态转移

     

     

     

     

     

     

     

     

     

     

     

     

     

     

     

     

     

     

     

    Hadoop提供了FailoverControllerActive和FailoverControllerStandBy两个进程用于监控NameNode的生命周期。

    FailoverControllerActive和FailoverControllerStandBy会分别监控对应状态的NameNode,若NameNode无异常则定期向Zookeeper集群发送心跳,若在一定时间内Zookeeper集群没收到FailoverControllerActive发送的心跳,则认为此时状态为Active的NameNode已经无法对外提供服务,因此将状态为StandBy的NameNode切换为Active状态。

     

    关于NameNode之间的数据如何进行同步

    Hadoop提供了JournalNode用于存放NameNode中的编辑日志,当状态为Active的NameNode节点执行任何名称空间上的修改时,它都会将修改保存到JournalNode集群中,而状态为StandBy的NameNode节点会实时的从JournalNode集群中进行同步。

     

    1.1 修改配置

     

    1.安装并配置Zookeeper集群

     

    2.配置HDFS(hdfs-site.xml)

    <configuration> 
      <!-- 指定NameService的名称 -->  
      <property> 
        <name>dfs.nameservices</name>  
        <value>mycluster</value> 
      </property>  
      <!-- 指定NameService下两个NameNode的名称 -->  
      <property> 
        <name>dfs.ha.namenodes.mycluster</name>  
        <value>nn1,nn2</value> 
      </property>  
      <!-- 分别指定NameNode的RPC通讯地址 -->  
      <property> 
        <name>dfs.namenode.rpc-address.mycluster.nn1</name>  
        <value>192.168.1.80:8020</value> 
      </property>  
      <property> 
        <name>dfs.namenode.rpc-address.mycluster.nn2</name>  
        <value>192.168.1.81:8020</value> 
      </property>  
      <!-- 分别指定NameNode的可视化管理界面的地址 -->  
      <property> 
        <name>dfs.namenode.http-address.mycluster.nn1</name>  
        <value>192.168.1.80:50070</value> 
      </property>  
      <property> 
        <name>dfs.namenode.http-address.mycluster.nn2</name>  
        <value>192.168.1.81:50070</value> 
      </property>  
      <!-- 指定NameNode编辑日志存储在JournalNode集群中的目录-->  
      <property> 
        <name>dfs.namenode.shared.edits.dir</name>  
        <value>qjournal://192.168.1.80:8485;192.168.1.81:8485;192.168.1.82:8485/mycluster</value> 
      </property>
      <!-- 指定JournalNode集群存放日志的目录-->  
      <property> 
        <name>dfs.journalnode.edits.dir</name>  
        <value>/usr/hadoop/hadoop-2.9.0/journalnode</value> 
      </property>  
      <!-- 配置NameNode失败自动切换的方式-->  
      <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>  
      <!-- 由于使用SSH,那么需要指定密钥的位置-->  
      <property> 
        <name>dfs.ha.fencing.ssh.private-key-files</name>  
        <value>/root/.ssh/id_rsa</value> 
      </property>  
      <!-- 开启失败故障自动转移-->  
      <property> 
        <name>dfs.ha.automatic-failover.enabled</name>  
        <value>true</value> 
      </property>  
      <!-- 配置Zookeeper地址-->  
      <property> 
        <name>ha.zookeeper.quorum</name>  
        <value>192.168.1.80:2181,192.168.1.81:2181,192.168.1.82:2181</value> 
      </property>  
      <!-- 文件在HDFS中的备份数(小于等于DataNode) -->  
      <property> 
        <name>dfs.replication</name>  
        <value>3</value> 
      </property>  
      <!-- 关闭HDFS的访问权限 -->  
      <property> 
        <name>dfs.permissions.enabled</name>  
        <value>false</value> 
      </property>  
      <!-- 指定一个配置文件,使NameNode过滤配置文件中指定的host -->  
      <property> 
        <name>dfs.hosts.exclude</name>  
        <value>/usr/hadoop/hadoop-2.9.0/etc/hadoop/hdfs.exclude</value> 
      </property> 
    </configuration>

    3.配置Hadoop公共属性(core-site.xml)

    <configuration> 
      <!-- Hadoop工作目录,用于存放Hadoop运行时产生的临时数据 -->
      <property> 
        <name>hadoop.tmp.dir</name>  
        <value>/usr/hadoop/hadoop-2.9.0/data</value> 
      </property>  
      <!-- 默认的NameNode,使用NameService的名称 -->  
      <property> 
        <name>fs.defaultFS</name>  
        <value>hdfs://mycluster</value> 
      </property>  
      <!-- 开启Hadoop的回收站机制,当删除HDFS中的文件时,文件将会被移动到回收站(/usr/<username>/.Trash),在指定的时间过后再对其进行删除,此机制可以防止文件被误删除 -->  
      <property> 
        <name>fs.trash.interval</name>  
        <!-- 单位是分钟 -->  
        <value>1440</value> 
      </property> 
    </configuration> 

    在HDFS HA集群中,StandBy的NameNode会对namespace进行checkpoint操作,因此就不需要在HA集群中运行SecondaryNameNode、CheckpintNode、BackupNode

     

    1.2 启动HDFS高可用集群

    1.分别启动JournalNode

     

     

     

     

     

     

     

     

     

    2.格式化第一个NameNode并启动

     

     

     

     

     

     

    3.第二个NameNode同步第一个NameNode的信息

     

     

    4.启动第二个NameNode

     

     

     

     

    5.启动Zookeeper集群

     

     

     

     

     

     

     

     

     

     

     

     

     

    6.格式化Zookeeper

     

    当格式化ZK后,ZK中将会多了hadoop-ha节点。

     

    7.重启HDFS集群

     

     

     

     

     

     

     

     

     

     

     

     

     

     

     

     

     

    当HDFS高可用集群启动后,可以分别访问NameNode的可视化管理界面查看NameNode的状态状态,http://192.168.1.80:50070http://192.168.1.81:50070

     

    img

    img

     

    8.模拟NameNode宕机,手动杀死进程。

     

     

     

     

    此时访问NameNode可视化管理界面,可以查看到主机名为hadoop1的NameNode节点其状态从StandBy切换成Active。

     

    img

     

    1.3 JAVA操作HDFS高可用集群

    由于在HDFS高可用集群中存在两个NameNode,且服务端暴露的是NameService,因此在通过JAVA连接HDFS高可用集群时需要使用Configuration实例进行相关的配置。

    /**
     * @Auther: ZHUANGHAOTANG
     * @Date: 2018/11/6 11:49
     * @Description:
     */
    public class HDFSUtils {
    ​
        private static Logger logger = LoggerFactory.getLogger(HDFSUtils.class);
    ​
        /**
         * NameNode Service
         */
        private static final String NAMESERVER_URL = "hdfs://mycluster:8020";
    ​
        /**
         * NameNode服务列表
         */
        private static final String[] NAMENODE_URLS = {"192.168.1.80:8020", "192.168.1.81:8020"};
    ​
        /**
         * HDFS文件系统连接对象
         */
        private static FileSystem fs = null;
    ​
        static {
            Configuration conf = new Configuration();
            //指定默认连接的NameNode,使用NameService的地址
            conf.set("fs.defaultFS", NAMESERVER_URL);
            //指定NameService的名称
            conf.set("dfs.nameservices", "mycluster");
            //指定NameService下的NameNode列表
            conf.set("dfs.ha.namenodes.mycluster", "nn1,nn2");
            //分别指定NameNode的RPC通讯地址
            conf.set("dfs.namenode.rpc-address.mycluster.nn1", NAMENODE_URLS[0]);
            conf.set("dfs.namenode.rpc-address.mycluster.nn2", NAMENODE_URLS[1]);
            //配置NameNode失败自动切换的方式
            conf.set("dfs.client.failover.proxy.provider.mycluster", "org.apache.hadoop.hdfs.server.namenode.ha.ConfiguredFailoverProxyProvider");
            try {
                fs = FileSystem.get(URI.create(NAMESERVER_URL), conf);
            } catch (IOException e) {
                logger.info("初始化HDFS连接失败:{}", e);
            }
        }
    ​
        /**
         * 创建目录
         */
        public static void mkdir(String dir) throws Exception {
            dir = NAMESERVER_URL + dir;
            if (!fs.exists(new Path(dir))) {
                fs.mkdirs(new Path(dir));
            }
        }
    ​
        /**
         * 删除目录或文件
         */
        public static void delete(String dir) throws Exception {
            dir = NAMESERVER_URL + dir;
            fs.delete(new Path(dir), true);
        }
    ​
        /**
         * 遍历指定路径下的目录和文件
         */
        public static List<String> listAll(String dir) throws Exception {
            List<String> names = new ArrayList<>();
            dir = NAMESERVER_URL + dir;
            FileStatus[] files = fs.listStatus(new Path(dir));
            for (FileStatus file : files) {
                if (file.isFile()) { //文件
                    names.add(file.getPath().toString());
                } else if (file.isDirectory()) { //目录
                    names.add(file.getPath().toString());
                } else if (file.isSymlink()) { //软或硬链接
                    names.add(file.getPath().toString());
                }
            }
            return names;
        }
    ​
        /**
         * 上传当前服务器的文件到HDFS中
         */
        public static void uploadLocalFileToHDFS(String localFile, String hdfsFile) throws Exception {
            hdfsFile = NAMESERVER_URL + hdfsFile;
            Path src = new Path(localFile);
            Path dst = new Path(hdfsFile);
            fs.copyFromLocalFile(src, dst);
        }
    ​
        /**
         * 通过流上传文件
         */
        public static void uploadFile(String hdfsPath, InputStream inputStream) throws Exception {
            hdfsPath = NAMESERVER_URL + hdfsPath;
            FSDataOutputStream os = fs.create(new Path(hdfsPath));
            BufferedInputStream bufferedInputStream = new BufferedInputStream(inputStream);
            byte[] data = new byte[1024];
            int len;
            while ((len = bufferedInputStream.read(data)) != -1) {
                if (len == data.length) {
                    os.write(data);
                } else { //最后一次读取
                    byte[] lastData = new byte[len];
                    System.arraycopy(data, 0, lastData, 0, len);
                    os.write(lastData);
                }
            }
            inputStream.close();
            bufferedInputStream.close();
            os.close();
        }
    ​
        /**
         * 从HDFS中下载文件
         */
        public static byte[] readFile(String hdfsFile) throws Exception {
            hdfsFile = NAMESERVER_URL + hdfsFile;
            Path path = new Path(hdfsFile);
            if (fs.exists(path)) {
                FSDataInputStream is = fs.open(path);
                FileStatus stat = fs.getFileStatus(path);
                byte[] data = new byte[(int) stat.getLen()];
                is.readFully(0, data);
                is.close();
                return data;
            } else {
                throw new Exception("File Not Found In HDFS");
            }
        }
    ​
    }

    2.搭建YARN高可用集群

    由于一个Yarn集群由一个ResourceManager节点和多个NodeManager节点组成,一旦ResourceManager节点宕机,那么YARN集群将不能进行资源的调度。

     

     

     

     

     

     

     

     

     

    Hadoop依赖Zookeeper实现YARN集群的高可用,首先启动两个ResourceManager,且由状态为Active的ResourceManager节点对外提供服务,而状态为StandBy的ResourceManager节点则负责数据的同步,一旦状态为Active的ResourceManager节点宕机,则状态为StandBy的ResourceManager节点将会切换为Active状态,对外提供服务。

     

    2.1 修改配置

     

    1.安装并配置Zookeeper集群

     

    2.配置YARN(yarn-site.xml)

    <configuration> 
      <!-- 配置Reduce取数据的方式是shuffle(随机) -->  
      <property> 
        <name>yarn.nodemanager.aux-services</name>  
        <value>mapreduce_shuffle</value> 
      </property>  
      <!-- 开启日志 -->  
      <property> 
        <name>yarn.log-aggregation-enable</name>  
        <value>true</value> 
      </property>  
      <!-- 设置日志的删除时间 -1:禁用,单位为秒 -->  
      <property> 
        <name>yarn.log-aggregation。retain-seconds</name>  
        <value>864000</value> 
      </property>  
      <!-- 设置yarn的内存大小,单位是MB -->  
      <property> 
        <name>yarn.nodemanager.resource.memory-mb</name>  
        <value>8192</value> 
      </property>  
      <!-- 设置yarn的CPU核数 -->  
      <property> 
        <name>yarn.nodemanager.resource.cpu-vcores</name>  
        <value>8</value> 
      </property>
      <!-- YARN HA配置 -->  
      <!-- 开启yarn ha -->  
      <property> 
        <name>yarn.resourcemanager.ha.enabled</name>  
        <value>true</value> 
      </property>  
      <!-- 指定yarn ha的名称 -->  
      <property> 
        <name>yarn.resourcemanager.cluster-id</name>  
        <value>cluster1</value> 
      </property>  
      <!-- 分别指定两个ResourceManager的名称 -->  
      <property> 
        <name>yarn.resourcemanager.ha.rm-ids</name>  
        <value>rm1,rm2</value> 
      </property>  
      <!-- 分别指定两个ResourceManager的地址 -->  
      <property> 
        <name>yarn.resourcemanager.hostname.rm1</name>  
        <value>192.168.1.80</value> 
      </property>  
      <property> 
        <name>yarn.resourcemanager.hostname.rm2</name>  
        <value>192.168.1.81</value> 
      </property>  
      <!-- 分别指定两个ResourceManager的Web访问地址 -->  
      <property> 
        <name>yarn.resourcemanager.webapp.address.rm1</name>  
        <value>192.168.1.80:8088</value> 
      </property>  
      <property> 
        <name>yarn.resourcemanager.webapp.address.rm2</name>  
        <value>192.168.1.81:8088</value> 
      </property>  
      <!-- 配置使用的Zookeeper集群 -->  
      <property> 
        <name>yarn.resourcemanager.zk-address</name>  
        <value>192.168.1.80:2181,192.168.1.81:2181,192.168.1.82:2181</value> 
      </property>  
      <!-- ResourceManager Restart配置 -->  
      <!-- 启用ResourceManager的restart功能,当ResourceManager重启时将会保存当前运行的信息到指定的位置,当重启成功后自动进行读取 -->  
      <property> 
        <name>yarn.resourcemanager.recovery.enabled</name>  
        <value>true</value> 
      </property>  
      <!-- ResourceManager Restart使用的存储方式(实现类) -->  
      <property> 
        <name>yarn.resourcemanager.store.class</name>  
        <value>org.apache.hadoop.yarn.server.resourcemanager.recovery.ZKRMStateStore</value> 
      </property>  
      <!-- ResourceManager重启时数据保存在Zookeeper中的目录 -->  
      <property> 
        <name>yarn.resourcemanager.zk-state-store.parent-path</name>  
        <value>/rmstore</value> 
      </property>  
      <!-- NodeManager Restart配置 -->  
      <!-- 启用NodeManager的restart功能,当NodeManager重启时将会保存当前运行时的信息到指定的位置,重启成功后自动进行读取 -->  
      <property> 
        <name>yarn.nodemanager.recovery.enabled</name>  
        <value>true</value> 
      </property>  
      <!-- NodeManager重启时数据保存在本地的目录 -->  
      <property> 
        <name>yarn.nodemanager.recovery.dir</name>  
        <value>/usr/hadoop/hadoop-2.9.0/data/rsnodemanager</value> 
      </property>  
      <!-- 配置NodeManager的RPC通讯端口 -->  
      <property> 
        <name>yarn.nodemanager.address</name>  
        <value>0.0.0.0:45454</value> 
      </property> 
    </configuration>

    ResourceManager Restart使用的存储方式(实现类)

    #保存在ZK当中
    org.apache.hadoop.yarn.server.resourcemanager.recovery.ZKRMStateStore
    ​
    #保存在HDFS中
    org.apache.hadoop.yarn.server.resourcemanager.recovery.FileSystemRMStateStore
    ​
    #保存在本地
    org.apache.hadoop.yarn.server.resourcemanager.recovery.LeveldbRMStateStore 

    使用不同的存储方式将需要额外的配置项,可参考官网,http://hadoop.apache.org/docs/current/hadoop-yarn/hadoop-yarn-site/ResourceManagerRestart.html

     

    2.2 启动YARN高可用集群

    1.在ResourceManager节点中启动YARN集群

     

     

     

     

     

     

     

     

     

    2.手动启动另一个ResourceManager

    img

     

    3.当启动YARN高可用集群后,可以分别访问ResourceManager的可视化管理界面,http://192.168.1.80:8088http://192.168.1.81:8088

    当访问状态为StandBy的ResourceManager时,将会将请求重定向到状态为Active的ResourceManager的可视化管理界面。

     

    4.模拟ResourceManager宕机,手动杀死进程。

     

     

     

     

     

    Zookeeper在一定时间内没有接收到状态为Active的ResourceManager发送的心跳时,将会立即将状态为StandBy的ResourceManager切换为Active。

  • 相关阅读:
    leetcode231 2的幂 leetcode342 4的幂 leetcode326 3的幂
    leetcode300. Longest Increasing Subsequence 最长递增子序列 、674. Longest Continuous Increasing Subsequence
    leetcode64. Minimum Path Sum
    leetcode 20 括号匹配
    算法题待做
    leetcode 121. Best Time to Buy and Sell Stock 、122.Best Time to Buy and Sell Stock II 、309. Best Time to Buy and Sell Stock with Cooldown 、714. Best Time to Buy and Sell Stock with Transaction Fee
    rand7生成rand10,rand1生成rand6,rand2生成rand5(包含了rand2生成rand3)
    依图
    leetcode 1.Two Sum 、167. Two Sum II
    从分类,排序,top-k多个方面对推荐算法稳定性的评价
  • 原文地址:https://www.cnblogs.com/funyoung/p/9947105.html
Copyright © 2011-2022 走看看