Hadoop05-HDFS2.X新特性和高可用(HA)

NiuMT 2020-06-03 20:58:30
Hadoop

HDFS 2.X新特性

集群间数据拷贝

采用distcp命令实现两个Hadoop集群之间的递归数据复制:

[atguigu@hadoop102 hadoop-2.7.2]$  bin/hadoop distcp hdfs://haoop102:9000/user/atguigu/hello.txt hdfs://hadoop103:9000/user/atguigu/hello.txt

小文件存档

  1. 每个文件均按块存储,每个块的元数据存储在NameNode的内存中,因此HDFS存储小文件会非常低效。因为大量的小文件会耗尽NameNode中的大部分内存。但注意,存储小文件所需要的磁盘容量和数据块的大小无关。例如,一个1MB的文件设置为128MB的块存储,实际使用的是1MB的磁盘空间,而不是128MB。
  2. HDFS存档文件或HAR文件,是一个更高效的文件存档工具,它将文件存入HDFS块,在减少NameNode内存使用的同时,允许对文件进行透明的访问。具体说来,HDFS存档文件对内还是一个一个独立文件,对NameNode而言却是一个整体,减少了NameNode的内存。

案例:

  1. 需要启动YARN进程:start-yarn.sh

  2. 归档文件

    把/user/atguigu/input目录里面的所有文件归档成一个叫input.har的归档文件,并把归档后文件存储到/user/atguigu/output路径下。

    [atguigu@hadoop102 hadoop-2.7.2]$ bin/hadoop archive -archiveName input.har –p  /user/atguigu/input   /user/atguigu/output
    
  3. 查看归档

    [atguigu@hadoop102 hadoop-2.7.2]$ hadoop fs -lsr /user/atguigu/output/input.har
    [atguigu@hadoop102 hadoop-2.7.2]$ hadoop fs -lsr har:///user/atguigu/output/input.har
    
  4. 解归档文件

    [atguigu@hadoop102 hadoop-2.7.2]$ hadoop fs -cp har:/// user/atguigu/output/input.har/*    /user/atguigu
    

回收站

开启回收站功能,可以将删除的文件在不超时的情况下,恢复原数据,起到防止误删除、备份等作用。

  1. 开启回收站功能参数说明:

    • 默认值fs.trash.interval=0,0表示禁用回收站;其他值表示设置文件的存活时间。
    • 默认值fs.trash.checkpoint.interval=0,检查回收站的间隔时间。如果该值为0,则该值设置和fs.trash.interval的参数值相等。
    • 要求fs.trash.checkpoint.interval<=fs.trash.interval。
  2. 回收站工作机制:

    image-20201220173843936

  3. 启用回收站

    修改core-site.xml,配置垃圾回收时间为1分钟

    <property>
        <name>fs.trash.interval</name>
        <value>1</value>
    </property>
    
  4. 查看回收站

    回收站在集群中的路径:/user/atguigu/.Trash/….

  5. 修改访问垃圾回收站用户名称

    进入垃圾回收站用户名称,默认是dr.who,修改为atguigu用户.

    修改core-site.xml

    <property>
      <name>hadoop.http.staticuser.user</name>
      <value>atguigu</value>
    </property>
    
  6. 通过程序删除的文件不会经过回收站,需要调用moveToTrash()才进入回收站

    Trash trash = New Trash(conf);

    trash.moveToTrash(path);

  7. 恢复回收站数据

    [atguigu@hadoop102 hadoop-2.7.2]$ hadoop fs -mv /user/atguigu/.Trash/Current/user/atguigu/input    /user/atguigu/input
    
  8. 清空回收站

    [atguigu@hadoop102 hadoop-2.7.2]$ hadoop fs -expunge
    

快照管理

快照相当于对目录做一个备份。并不会立即复制所有文件,而是记录文件变化。

  1. 参数描述:

    • hdfs dfsadmin -allowSnapshot 路径 (功能描述:开启指定目录的快照功能)
    • hdfs dfsadmin -disallowSnapshot 路径 (功能描述:禁用指定目录的快照功能,默认是禁用)
    • hdfs dfs -createSnapshot 路径 (功能描述:对目录创建快照)
    • hdfs dfs -createSnapshot 路径 名称 (功能描述:指定名称创建快照)
    • hdfs dfs -renameSnapshot 路径 旧名称 新名称 (功能描述:重命名快照)
    • hdfs lsSnapshottableDir (功能描述:列出当前用户所有可快照目录)
    • hdfs snapshotDiff 路径1 路径2 (功能描述:比较两个快照目录的不同之处)
    • hdfs dfs -deleteSnapshot (功能描述:删除快照)
  2. 开启/禁用指定目录的快照功能

    [atguigu@hadoop102 hadoop-2.7.2]$ hdfs dfsadmin -allowSnapshot /user/atguigu/input
    
    [atguigu@hadoop102 hadoop-2.7.2]$ hdfs dfsadmin -disallowSnapshot /user/atguigu/input
    
  3. 对目录创建快照

    [atguigu@hadoop102 hadoop-2.7.2]$ hdfs dfs -createSnapshot /user/atguigu/input
    # 通过web访问hdfs://hadoop102:50070/user/atguigu/input/.snapshot/s…..// 快照和源文件使用相同数据
    [atguigu@hadoop102 hadoop-2.7.2]$ hdfs dfs -lsr /user/atguigu/input/.snapshot/
    
  4. 指定名称创建快照

    [atguigu@hadoop102 hadoop-2.7.2]$ hdfs dfs -createSnapshot /user/atguigu/input  miao170508
    
  5. 重命名快照

    [atguigu@hadoop102 hadoop-2.7.2]$ hdfs dfs -renameSnapshot /user/atguigu/input/  miao170508 atguigu170508
    
  6. 列出当前用户所有可快照目录

    [atguigu@hadoop102 hadoop-2.7.2]$ hdfs lsSnapshottableDir
    
  7. 比较两个快照目录的不同之处

    [atguigu@hadoop102 hadoop-2.7.2]$ hdfs snapshotDiff /user/atguigu/input/  .  .snapshot/atguigu170508
    
  8. 恢复快照

    atguigu@hadoop102 hadoop-2.7.2]$ hdfs dfs -cp /user/atguigu/input/.snapshot/s20170708-134303.027 /user
    

HDFS HA高可用

HA概述

所谓HA(High Available),即高可用(7*24小时不中断服务)。实现高可用最关键的策略是消除单点故障。HA严格来说应该分成各个组件的HA机制:HDFS的HA和YARN的HA。

Hadoop2.0之前,在HDFS集群中NameNode存在单点故障(SPOF)。NameNode主要在以下两个方面影响HDFS集群:

HDFS-HA工作机制

通过双NameNode消除单点故障

工作要点

  1. 元数据管理方式需要改变

    内存中各自保存一份元数据;

    Edits日志只有Active状态的NameNode节点可以做写操作;

    两个NameNode都可以读取Edits;

    共享的Edits放在一个共享存储中管理(qjournal和NFS两个主流实现);

  2. 需要一个状态管理功能模块

    实现了一个zkfailover,常驻在每一个namenode所在的节点,每一个zkfailover负责监控自己所在NameNode节点,利用zk进行状态标识,当需要进行状态切换时,由zkfailover来负责切换,切换时需要防止brain split现象的发生。

  3. 必须保证两个NameNode之间能够ssh无密码登录

  4. 隔离(Fence),即同一时刻仅仅有一个NameNode对外提供服务

自动故障转移工作机制

前面学习了使用命令hdfs haadmin -failover手动进行故障转移,在该模式下,即使现役NameNode已经失效,系统也不会自动从现役NameNode转移到待机NameNode,下面学习如何配置部署HA自动进行故障转移。自动故障转移为HDFS部署增加了两个新组件:ZooKeeper和ZKFailoverController(ZKFC)进程,如图所示。ZooKeeper是维护少量协调数据,通知客户端这些数据的改变和监视客户端故障的高可用服务。HA的自动故障转移依赖于ZooKeeper的以下功能:

  1. 故障检测:集群中的每个NameNode在ZooKeeper中维护了一个持久会话,如果机器崩溃,ZooKeeper中的会话将终止,ZooKeeper通知另一个NameNode需要触发故障转移。
  2. 现役NameNode选择:ZooKeeper提供了一个简单的机制用于唯一的选择一个节点为active状态。如果目前现役NameNode崩溃,另一个节点可能从ZooKeeper获得特殊的排外锁以表明它应该成为现役NameNode。

image-20201220084525214

ZKFC是自动故障转移中的另一个新组件,是ZooKeeper的客户端,也监视和管理NameNode的状态。每个运行NameNode的主机也运行了一个ZKFC进程,ZKFC负责:

  1. 健康监测:ZKFC使用一个健康检查命令定期地ping与之在相同主机的NameNode,只要该NameNode及时地回复健康状态,ZKFC认为该节点是健康的。如果该节点崩溃,冻结或进入不健康状态,健康监测器标识该节点为非健康的。
  2. ZooKeeper会话管理:当本地NameNode是健康的,ZKFC保持一个在ZooKeeper中打开的会话。如果本地NameNode处于active状态,ZKFC也保持一个特殊的znode锁,该锁使用了ZooKeeper对短暂节点的支持,如果会话终止,锁节点将自动删除。
  3. 基于ZooKeeper的选择:如果本地NameNode是健康的,且ZKFC发现没有其它的节点当前持有znode锁,它将为自己获取该锁。如果成功,则它已经赢得了选择,并负责运行故障转移进程以使它的本地NameNode为Active。故障转移进程与前面描述的手动故障转移相似,首先如果必要保护之前的现役NameNode,然后本地NameNode转换为Active状态。

HDFS-HA集群配置

规划集群

hadoop102 hadoop103 hadoop104
NameNode NameNode
JournalNode JournalNode JournalNode
DataNode DataNode DataNode
ZK ZK ZK
ResourceManager
NodeManager NodeManager NodeManager

配置HDFS-HA集群

  1. 复制已有的 hadoop-2.7.2 到新目录下;

  2. 配置core-site.xml

    <configuration>
        <!-- 把两个NameNode)的地址组装成一个集群mycluster -->
        <property>
            <name>fs.defaultFS</name>
            <value>hdfs://mycluster</value>
        </property>
        <!-- 指定hadoop运行时产生文件的存储目录 -->
        <property>
            <name>hadoop.tmp.dir</name>
            <value>/opt/ha/hadoop-2.7.2/data/tmp</value>
        </property>
        <property>
            <name>dfs.journalnode.edits.dir</name>
            <value>/opt/module/HA/hadoop-2.7.2/data/tmp/jn</value>
        </property>
    </configuration>
    
  3. 配置hdfs-site.xml

    <configuration>
        <!-- 完全分布式集群名称 -->
        <property>
            <name>dfs.nameservices</name>
            <value>mycluster</value>
        </property>
    
        <!-- 集群中NameNode节点都有哪些 -->
        <property>
            <name>dfs.ha.namenodes.mycluster</name>
            <value>nn1,nn2</value>
        </property>
    
        <!-- nn1的RPC通信地址 -->
        <property>
            <name>dfs.namenode.rpc-address.mycluster.nn1</name>
            <value>hadoop102:9000</value>
        </property>
    
        <!-- nn2的RPC通信地址 -->
        <property>
            <name>dfs.namenode.rpc-address.mycluster.nn2</name>
            <value>hadoop103:9000</value>
        </property>
    
        <!-- nn1的http通信地址 -->
        <property>
            <name>dfs.namenode.http-address.mycluster.nn1</name>
            <value>hadoop102:50070</value>
        </property>
    
        <!-- nn2的http通信地址 -->
        <property>
            <name>dfs.namenode.http-address.mycluster.nn2</name>
            <value>hadoop103:50070</value>
        </property>
    
        <!-- 指定NameNode元数据在JournalNode上的存放位置 -->
        <property>
            <name>dfs.namenode.shared.edits.dir</name>
            <value>qjournal://hadoop102:8485;hadoop103:8485;hadoop104:8485/mycluster</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>/home/atguigu/.ssh/id_rsa</value>
        </property>
    
        <!-- 声明journalnode服务器存储目录-->
        <property>
            <name>dfs.journalnode.edits.dir</name>
            <value>/opt/ha/hadoop-2.7.2/data/jn</value>
        </property>
    
        <!-- 关闭权限检查-->
        <property>
            <name>dfs.permissions.enable</name>
            <value>false</value>
        </property>
    
        <!-- 访问代理类:client,mycluster,active配置失败自动切换实现方式-->
        <property>
              <name>dfs.client.failover.proxy.provider.mycluster</name>
            <value>org.apache.hadoop.hdfs.server.namenode.ha.ConfiguredFailoverProxyProvider</value>
        </property>
    </configuration>
    
    1. 拷贝配置好的hadoop环境到其他节点
    2. 注意:这些参数读取后为K-V对儿,参数写错文件也没事。

启动HDFS-HA集群

  1. 三台机器分别启动zookeeper。

  2. 各个JournalNode节点上,输入以下命令启动journalnode服务

    sbin/hadoop-daemon.sh start journalnode

  3. 在[nn1]上,对其进行格式化,并启动:

    bin/hdfs namenode -format

    sbin/hadoop-daemon.sh start namenode

  4. 在[nn2]上,同步nn1的元数据信息,并启动 [nn2]

    bin/hdfs namenode -bootstrapStandby

    sbin/hadoop-daemon.sh start namenode

  5. 查看web页面显示

    image-20201220171655554 image-20201220171700608

  6. 在[nn1]上,启动所有datanode

    sbin/hadoop-daemons.sh start datanode

  7. 将[nn1]切换为Active

    bin/hdfs haadmin -transitionToActive nn1

  8. 查看是否Active

    bin/hdfs haadmin -getServiceState nn1

  9. 为了防止脑裂,手动模式下两个NameNode必须都起来才能切换NameNode。自动故障转移会自动切换NameNode,因为zkfc会kill -9 原先的NameNode进程,防止脑裂。

配置HDFS-HA自动故障转移

  1. 增加 hdfs-site.xml 配置

    <property>
        <name>dfs.ha.automatic-failover.enabled</name>
        <value>true</value>
    </property>
    
  2. 增加 core-site.xml 配置

    <property>
        <name>ha.zookeeper.quorum</name>
        <value>hadoop102:2181,hadoop103:2181,hadoop104:2181</value>
    </property>
    
  3. 启动

    # 关闭所有HDFS服务:NameNode、DataNode、journalnode、zkfc
    sbin/stop-dfs.sh
    
    # 在各个机器启动Zookeeper集群
    bin/zkServer.sh start
    
    # 初始化HA在Zookeeper中状态,然后在Zookeeper根目录下有集群节点
    bin/hdfs zkfc -formatZK
    
    # 启动HDFS服务
    sbin/start-dfs.sh
    
    # 在各个NameNode节点上启动DFSZK Failover Controller,先在哪台机器启动,哪个机器的NameNode就是Active NameNode
    sbin/hadoop-daemin. sh start zkfc
    

YARN-HA配置

YARN-HA工作机制

image-20201220172257423

配置YARN-HA集群

hadoop102 hadoop103 hadoop104
NameNode NameNode
JournalNode JournalNode JournalNode
DataNode DataNode DataNode
ZK ZK ZK
ResourceManager ResourceManager
NodeManager NodeManager NodeManager
  1. 配置 yarn-site.xml

    <configuration>
        <property>
            <name>yarn.nodemanager.aux-services</name>
            <value>mapreduce_shuffle</value>
        </property>
    
        <!--启用resourcemanager ha-->
        <property>
            <name>yarn.resourcemanager.ha.enabled</name>
            <value>true</value>
        </property>
    
        <!--声明两台resourcemanager的地址-->
        <property>
            <name>yarn.resourcemanager.cluster-id</name>
            <value>cluster-yarn1</value>
        </property>
    
        <property>
            <name>yarn.resourcemanager.ha.rm-ids</name>
            <value>rm1,rm2</value>
        </property>
    
        <property>
            <name>yarn.resourcemanager.hostname.rm1</name>
            <value>hadoop102</value>
        </property>
    
        <property>
            <name>yarn.resourcemanager.hostname.rm2</name>
            <value>hadoop103</value>
        </property>
    
        <!--指定zookeeper集群的地址--> 
        <property>
            <name>yarn.resourcemanager.zk-address</name>
            <value>hadoop102:2181,hadoop103:2181,hadoop104:2181</value>
        </property>
    
        <!--启用自动恢复--> 
        <property>
            <name>yarn.resourcemanager.recovery.enabled</name>
            <value>true</value>
        </property>
    
        <!--指定resourcemanager的状态信息存储在zookeeper集群--> 
        <property>
            <name>yarn.resourcemanager.store.class</name>
            <value>org.apache.hadoop.yarn.server.resourcemanager.recovery.ZKRMStateStore</value>
    </property>
    
    </configuration>
    
  2. 同步更新其他节点的配置信息

  3. 启动hdfs

    # 已经格式化NameNode了,这里不需要再格式化
    # 启动HFDS
    sbin/start-dfs.sh
    
  4. 启动YARN

    # 在hadoop102中执行
    sbin/start-yarn.sh
    
    # 在hadoop103中执行
    sbin/yarn-daemon.sh start resourcemanager
    
  5. 查看服务状态

    image-20201220172529956

  6. 注意:执行start-yarn.sh并不能启动103的RM,需要单独在103启动RM,此时102为active。访问103:8088会自动跳转到102:8088。如果kill -9 102RM,无法访问102:8088,103RM自动提升为active,103:8088不再跳转。

HDFS Federation结构设计

  1. NameNode架构的局限性

    • Namespace(命名空间)的限制

      由于NameNode在内存中存储所有的元数据(metadata),因此单个NameNode所能存储的对象(文件+块)数目受到NameNode所在JVM的heap size的限制。50G的heap能够存储20亿(200million)个对象,这20亿个对象支持4000个DataNode,12PB的存储(假设文件平均大小为40MB)。随着数据的飞速增长,存储的需求也随之增长。单个DataNode从4T增长到36T,集群的尺寸增长到8000个DataNode。存储的需求从12PB增长到大于100PB。

    • 隔离问题

      由于HDFS仅有一个NameNode,无法隔离各个程序,因此HDFS上的一个实验程序就很有可能影响整个HDFS上运行的程序。

    • 性能的瓶颈

      由于是单个NameNode的HDFS架构,因此整个HDFS文件系统的吞吐量受限于单个NameNode的吞吐量。

  2. HDFS Federation架构设计

    能不能有多个NameNode

    | NameNode | NameNode | NameNode |
    | ———— | ———— | ————————- |
    | 元数据 | 元数据 | 元数据 |
    | Log | machine | 电商数据/话单数据 |

    image-20201220172931340

  3. HDFS Federation应用思考

    不同应用可以使用不同NameNode进行数据管理

    图片业务、爬虫业务、日志审计业务

    Hadoop生态系统中,不同的框架使用不同的NameNode进行管理NameSpace。(隔离性)