Hadoop(HDFS)知识点总结

第1章 HDFS概论

1.1 HDFS产生背景及定义

1.1.1 HDFS产生背景

随着数据量越来越大,在一个操作系统存不下所有的数据,那么就分配到更多的操作系 统管理的磁盘中,但是不方便管理和维护,迫切需要一种系统来管理堕胎机器上的文件, 这就是分布式文件管理系统;HDFS只是分布式文件管理系统中的一种

1.1.2 HDFS定义

HDFS(Hadoop Distributed File System)它是一个文件系统,用于存储文件,通过目录树来定位文件;其次,它是分布式的,由很多服务器联合起来实现其功能,集群中的服务器 有各自的角色

HDFS的使用场景:适合一次写入,多次读出的场景,且不支持文件的修改。适合用来做数据分析,并不适合用来做网盘应用

1.2 HDFS优缺点

1.2.1 优点(高容错性/高可用/高扩展)

A. 高容错性

· 数据自动保存多个副本;它通过增加副本的形式,提高容错性

· 某一个副本丢失以后,它可以自动恢复

B. 适合处理大数据

· 数据规模:能够处理数据规模达到GB、TB、甚至PB级别的数据

· 文件规模:能够处理百万规模以上的文件数量,数量相当之大

C. 可构建在廉价的机器上,通过多副本机制,提高可靠性

1.2.2 缺点

A. 不适合低延时数据访问,比如毫秒的存储数据,是做不到的

B. 无法高效的对大量小文件进行存储

· 存储大量小文件的话,会占用NameNode大量的内存来存储文件目录和块信息;这样是不可取的,因为NameNode的内存总是有限的

· 小文件存储的寻址时间会超过读取时间,违反了HDFS的设计目标

C. 不支持并发写入、文件随机修改

· 同一时间一个文件只能有一个用户执行写操作,不允许多个线程同时写

· 仅支持数据append(追加),不支持文件的随机修改

1.3 HDFS组成架构

在这里插入图片描述

A. NameNode(nn):就是Master,它是一个主管、管理者

· 管理HDFS的名称空间

· 配置副本策略

· 管理数据块(Block)映射信息

· 处理客户端读写请求

B. DataNode:就是Slave,NameNode下达命令,DataNode执行实际的操作

C. Client:就是客户端

· 文件切分;文件上传HDFS的时候,Client将文件切分成一个一个的Block,然后进行上传

· 与NameNode交互,读取文件的位置信息

· 与DataNode交互,读取或者写入数据

· Client提供一些命令来管理HDFS,比如NameNode格式化

· Client可以通过一些命令来访问HDFS,比如对HDFS增删改查操作

D. SecondaryNameNode:并非NameNode的热备;当NameNode挂掉的时候,它并不 能马上替换NameNode并提供服务

· 辅助NameNode,分担工作量,如定期合并simage和Edits,并推送给NameNode

· 在紧急情况下,可辅助恢复NameNode

1.4 HDFS文件块大小

HDFS中的文件在物理上是分块存储(Block), 块的大小可以通过配置参数(dfs.blocksize)来规定,默认大小在Hadoop2.x版本中是128M,老版本中是64M

  • 为什么块的大小不能设置太小,也不能设置太大?

HDFS的块设置太小,会增加寻址时间,程序一直在找块的开始位置;

如果块设置的太大,从磁盘传输数据的时间会明显大于定位这个块开始位置所需的时 间;导致程序在处理这块数据时,会非常慢

  • 总结:HDFS块的大小设置主要取决于磁盘传输速率

第2章 HDFS的Shell操作

A.基础语法

bin/hadoop fs 具体命令 or bin/hdfs dfs 具体命令

dfs是fs的实现类

B.常用命令操作(一定要注意hadoop下的hdfs-site.xml中配置的节点数一定要和启动的 datanode节点数一致,只能大不能小)

· 启动hadoop集群:start-dfs.sh start-yarn.sh

· 输出命令参数:-help rm

本地文件 -> HDFS

-put    将本地数据上传至hdfs
-copyFromLocal    将本地文件数据拷贝到hdfs
-moveFromLocal    将本地文件数据移动到hdfs,成功后本地数据会删除
-appendToFile    追加一个文件到已经存在的文件末尾

HDFS与HDFS之间

-ls    查看hdfs文件目录
-mkdir    在HDFS上创建目录
-rm    删除文件或者文件夹
-rmr    递归删除
-cp    从一个目录拷贝文件至另一目录
-mv    在HDFS目录中移动文件
-chown    修改文件所属用户权限
-chmod    修改文件所属读写权限
-du -h    文件夹暂用的空间大小
-df -h    查看系统分区情况
-cat    查看文件
-tail:显示一个文件的末尾
-setrep:设置hdfs中文件的副本数量

HFDS -> 本地

-get    从hdfs下载文件至本地
-getmerge    合并hdfs目录下的文件至本地
-copyToLocal    从hdfs拷贝文件至本地

第3章 HDFS客户端操作

3.1 HDFS客户端环境准备

3.1.1 根据自己电脑的操作系统拷贝对应的编译后的hadoop jar包到非中文路径
3.1.2 配置HADOOP_HOME环境变量
3.1.3 配置path环境变量
3.1.4 创建一个Maven工程HdfsClient
3.1.5 导入相应的依赖坐标+日志添加
<dependencies>
	<dependency>
		<groupId>junit</groupId>
		<artifactId>junit</artifactId>
		<version>RELEASE</version>
	</dependency>
	<dependency>
		<groupId>org.apache.logging.log4j</groupId>
		<artifactId>log4j-core</artifactId>
		<version>2.8.2</version>
	</dependency>
	<dependency>
		<groupId>org.apache.hadoop</groupId>
		<artifactId>hadoop-common</artifactId>
		<version>2.7.2</version>
	</dependency>
	<dependency>
		<groupId>org.apache.hadoop</groupId>
		<artifactId>hadoop-client</artifactId>
		<version>2.7.2</version>
	</dependency>
	<dependency>
		<groupId>org.apache.hadoop</groupId>
		<artifactId>hadoop-hdfs</artifactId>
		<version>2.7.2</version>
	</dependency>
	<dependency>
		<groupId>jdk.tools</groupId>
		<artifactId>jdk.tools</artifactId>
		<version>1.8</version>
		<scope>system</scope>
		<systemPath>${JAVA_HOME}/lib/tools.jar</systemPath>
	</dependency>
</dependencies>

如果Eclipse/Idea打印不出日志,在控制tai上只显示

1.log4j:WARN No appenders could be found for logger (org.apache.hadoop.util.Shell). 
2.log4j:WARN Please initialize the log4j system properly. 
3.log4j:WARN See http://logging.apache.org/log4j/1.2/faq.html#noconfig for more info.

需要在项目的src/main/resources目录下,新建一个文件,命名为“log4j.properties”,在文件中填入

log4j.rootLogger=INFO, stdout
log4j.appender.stdout=org.apache.log4j.ConsoleAppender
log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
log4j.appender.stdout.layout.ConversionPattern=%d %p [%c] - %m%n
log4j.appender.logfile=org.apache.log4j.FileAppender
log4j.appender.logfile.File=target/spring.log
log4j.appender.logfile.layout=org.apache.log4j.PatternLayout
log4j.appender.logfile.layout.ConversionPattern=%d %p [%c] - %m%n
3.1.6 创建包名:com.jinghang.hdfsclient
3.1.7 创建HdfsClient类
public class HdfsClient {
    private Configuration configuration;
    private FileSystem fileSystem;
    @Before
    public void init() throws IOException, InterruptedException {
        System.out.println("----执行开始----");
        this.configuration = new Configuration();
        this.fileSystem = FileSystem.get(
        // URI:统一资源标识符(包含URL、URN)
        // URL:统一资源定位符
        // URN:统一资源名称
        URI.create("hdfs://hadoop01:9000") ,
        configuration ,
        "jinghang"
        ); // alt+enter
	}
	@After
    public void after() throws IOException {
        fileSystem.close();
        System.out.println("----执行完毕----");
    }
}
    

3.2 HDFS的API操作

参数优先级排序(从高到低):

· 客户端代码中设置的值

· classpath下的用户自定义配置文件

· 服务器的默认设置

3.2.1 HDFS文件上传
@Test
public void put() throws IOException, InterruptedException {
    // 本地文件路径D:\jinghang\Java\java\jh_java_01
    Path localPath = new Path("D:\\jinghang\\Java\\java\\jh_java_01");
    // hdfs文件路径
    Path hdfsPath = new Path("/code01/");
    // 将本地文件上传至hdfs通过copyFromFile方法
    fileSystem.copyFromLocalFile(localPath, hdfsPath);
    // 关闭文件系统
    fileSystem.close();
}
3.2.2 HDFS文件下载
@Test
public void get() throws IOException {
    // hdfs文件路径
    Path hdfsPath = new Path("/code1/hdfs.txt");
    // 本地文件路径
    Path localPath = new Path("D:\\jinghang\\Java\\idea\\aa");
    // 使用copyLocalFile将hdfs文件下载到本地
    fileSystem.copyFromLocalFile(hdfsPath, localPath);
}
3.2.3 HDFS文件夹删除
@Test
public void delete() throws IOException {
    // 指定需要删除的文件的路径
    Path hdfsPath = new Path("/code01");
    boolean b = fileSystem.delete(hdfsPath, true);
    if (b) {
    	System.out.println("文件删除成功");
    } else {
    	System.out.println("文件删除失败");
    }
}
3.2.4 HDFS文件名更改
@Test
public void rename() throws IOException {
    // 获取需要重命名的文件的路径
    Path hdfsPath = new Path("/code01");
    // 重命名的名称
    Path newPath = new Path("/code1");
    boolean b = fileSystem.rename(hdfsPath, newPath);
    if (b) {
    	System.out.println("文件名修改成功");
    } else {
    	System.out.println("文件名修改失败");
    }
}
3.2.5 HDFS文件追加
@Test
public void append() throws IOException {
    // 要追加的文件路径(hdfs)
    Path hdfsPath = new Path("/code1/.classpath");
    // 本地文件的路径
    String localPath = "D:\\jinghang\\Java\\java\\jh_java_01\\.project";
    // hdfs的文件输出流
    FSDataOutputStream append = fileSystem.append(hdfsPath, 1024);
    // 本地文件的输入流
    FileInputStream inputStream = new FileInputStream(localPath);
    IOUtils.copyBytes(inputStream, append, 1024, true);
    // 手动关闭输入流和输出流
    inputStream.close();
    append.close();
}
3.2.6 HDFS文件和文件夹判断
@Test
public void readFileAndDir() throws IOException {
	// listStatus:读取文件和文件夹
	Path hdfsPath = new Path("/code1/src/");
	FileStatus[] fileStatuses = fileSystem.listStatus(hdfsPath);
	for (FileStatus fileStatus : fileStatuses) {
		if (fileStatus.isDirectory()) {
			System.out.println("是一个文件夹");
            System.out.println(fileStatus.getPath());  // 路径
            System.out.println(fileStatus.getLen());  // 文件长度
            System.out.println(fileStatus.getPermission()); // 文件的权限
            System.out.println(fileStatus.getOwner()); // 文件夹的所有者
            System.out.println(fileStatus.getGroup()); // 文件夹的所属组
        } else {
            System.out.println("是一个文件");
            System.out.println(fileStatus.getPath());  // 路径
            System.out.println(fileStatus.getLen());  // 文件长度
            System.out.println(fileStatus.getReplication());  // 副本数
            System.out.println(fileStatus.getBlockSize()); // 块大小
		}
	}
}

3.3 HDFS的I/O流操作

3.3.1 HDFS文件上传
@Test
public void cusPut() throws IOException {
    // 获取去本地文件作为输入流
    String localPath = "D:\\jinghang\\IDEA2019.1\\Install-Windows-zip.txt";
    FileInputStream inputStream = new FileInputStream(localPath);
    // 获取hdfs的输出流
    Path hdfsPath = new Path("/code2");
    FSDataOutputStream outputStream = fileSystem.create(hdfsPath);
    IOUtils.copyBytes(inputStream, outputStream, configuration, true);
    // 手动关闭
    outputStream.close();
    inputStream.close();
}
3.3.2 HDFS文件下载
@Test
public void cusGet() throws IOException {
    //hdfs文件作为输入流
    Path hdfsPath = new Path("/code2");
    FSDataInputStream open = fileSystem.open(hdfsPath);
    //添加本地的输出流(指定下载后的文件的文件名)
    String localPath = "D:\\jinghang\\Java\\idea\\aa\\a.txt";
    FileOutputStream outputStream = new FileOutputStream(localPath);
    IOUtils.copyBytes(open, outputStream, configuration, true);
}

第4章 HDFS的数据流

4.1 HDFS写数据流程

4.1.1 刨析文件写入

在这里插入图片描述

A.客户端通过Distributed FileSystem模块向NameNode请求上传文件,NameNode检查目标文件是否已存在,父目录是否存在

B.NameNode返回是否可以上传

C.客户端请求第一个 Block上传到哪几个DataNode服务器上

D.NameNode返回3个DataNode节点,分别为dn1、dn2、dn3

E.客户端通过FSDataOutputStream模块请求dn1上传数据,dn1收到请求会继续调用dn2,然后dn2调用dn3,将这个通信管道建立完成

F.dn1、dn2、dn3逐级应答客户端

G.客户端开始往dn1上传第一个Block(先从磁盘读取数据放到一个本地内存缓存),以Packet为单位,dn1收到一个Packet就会传给dn2,dn2传给dn3;dn1每传一个packet会放入一个应答队列等待应答

H.当一个Block传输完成之后,客户端再次请求NameNode上传第二个Block的服务器。(重复执行3-7步)

4.1.2 网络拓扑-节点距离计算

在HDFS写数据的过程中,NameNode会选择距离待上传数据最近距离的DataNode接 收数据。那么这个最近距离怎么计算呢?

节点距离:两个节点到达最近的共同祖先的距离总和

在这里插入图片描述

4.1.3 机架感知(副本存储节点选择)

A.官方ip地址

机架感知说明:http://hadoop.apache.org/docs/r2.7.2/hadoop-project-dist/hadoop-hdfs/HdfsDesign.html#Data_Replication

B.Hadoop2.7.2副本节点选择

· 第一个副本在Client所处的节点上。如果客户端在集群外,随机选一个

· 第二个副本和第一个副本位于相同机架,随机节点

· 第三个副本位于不同机架,随机节点

C. 副本节点选择的作用

减少网络的IO传输,提高安全性

4.2 HDFS读数据流程

在这里插入图片描述

A.客户端通过Distributed FileSystem向NameNode请求下载文件,NameNode通过查询元数据,找到文件块所在的DataNode地址

B.挑选一台DataNode(就近原则,然后随机)服务器,请求读取数据

C.DataNode开始传输数据给客户端(从磁盘里面读取数据输入流,以Packet为单位来做校验)

D.客户端以Packet为单位接收,先在本地缓存,然后写入目标文件

第5章 NameNode和SecondaryNameNode

5.1 NN和2NN工作机制

在这里插入图片描述

A.第一阶段:NameNode启动

·第一次启动NameNode格式化后,创建Fsimage和Edits文件。如果不是第一次启动,直接加载编辑日志和镜像文件到内存
·客户端对元数据进行增删改的请求
·NameNode记录操作日志,更新滚动日志
·NameNode在内存中对元数据进行增删改

B.第二阶段:SecondaryNameNode工作

·Secondary NameNode询问NameNode是否需要CheckPoint。直接带回NameNode是否检查结果
·Secondary NameNode请求执行CheckPoint
·NameNode滚动正在写的Edits日志
·将滚动前的编辑日志和镜像文件拷贝到Secondary NameNode
·Secondary NameNode加载编辑日志和镜像文件到内存,并合并
·生成新的镜像文件fsimage.chkpoint
·拷贝fsimage.chkpoint到NameNode
·NameNode将fsimage.chkpoint重新命名成fsimage

5.2 Fsimage和Edits解析

· Fsimage文件:HDFS文件系统元数据的一个永久性的检查点,其中包含HDFS文件 系统的所有目录和文件inode的序列化信息

· Edits文件:存放HDFS文件系统的所有更新操作的路径,文件系统客户端执行的所有 写操作首先会被记录到Edits文件中

· seen_txid文件保存的是一个数字,就是最后一个edits_的数字

· 每次NameNode启动的时候都会将Fsimage文件读入内存,加载Edits里面的更新操 作,保证内存中的元数据信息是最新的、同步的,可以看成NameNode启动的时候就 将Fsimage和Edits文件进行了合并

5.3 CheckPoint时间设置

A.通常情况下,SecondaryNameNode每隔一个小时执行一次

hdfs-default.xml

<property>
	<name>dfs.namenode.checkpoint.period</name>
	<value>3600</value>
</property>

B.一分钟检查一次操作次数,当操作次数达到1百万时,SecondaryNameNode执行一次

<property>
	<name>dfs.namenode.checkpoint.txns</name>
	<value>1000000</value>
	<description>操作动作次数</description>
</property>
<property>
	<name>dfs.namenode.checkpoint.check.period</name>
	<value>60</value>
	<description> 1分钟检查一次操作次数</description>
</property >

5.4 NameNode故障处理

NameNode故障后,可以采用如下两种方法恢复数据

A.将SecondaryNameNode中数据拷贝到NameNode存储数据的目录

· kill -9 NameNode进程

· 删除NameNode存储的数据:rm -rf /opt/module/hadoop-2.7.2/data/tmp/dfs/name/*

· 拷贝SecondaryNameNode中数据到原NameNode存储数据目录

· 重新启动NameNode

B.使用-importCheckpoint选项启动NameNode守护进程,从而将SecondaryNameNode中数据拷贝到NameNode目录中

· 修改hdfs-site.xml中的

<property>
	<name>dfs.namenode.checkpoint.period</name>
	<value>120</value>
</property>
<property>
	<name>dfs.namenode.name.dir</name>
	<value>/opt/module/hadoop-2.7.2/data/tmp/dfs/name</value>
</property>

· kill -9 NameNode进程

· 删除NameNode存储的数据:rm -rf /opt/module/hadoop-2.7.2/data/tmp/dfs/name/*

· 如果SecondaryNameNode和NameNode不在一个主机节点上,需要将SecondaryNameNode存储数据的目录拷贝到NameNode存储数据的平级目录,并删除in_use.lock文件

· 导入检查点数据(等待一会ctrl+c结束掉):bin/hdfs namenode -importCheckpoint

· 启动NameNode

5.5 集群安全模式

5.5.1 概述

A.NameNode启动

NameNode启动时,首先将镜像文件(Fsimage)载入内存,并执行编辑日志(Edits)中的各项操作。一旦在内存中成功建立文件系统元数据的映像,则创建一个新的Fsimage文件和一个空的编辑日志。此时,NameNode开始监听DataNode请求。这个过程期间,NameNode一直运行在安全模式,即NameNode的文件系统对于客户端来说是只读的

B.DataNode启动

系统中的数据块的位置并不是由NameNode维护的,而是以块列表的形式存储在DataNode中。在系统的正常操作期间,NameNode会在内存中保留所有块位置的映射信息。在安全模式下,各个DataNode会向NameNode发送最新的块列表信息,NameNode了解到足够多的块位置信息之后,即可高效运行文件系统

C.安全模式推出判断

如果满足“最小副本条件”,NameNode会在30秒钟之后就退出安全模式。所谓的最小副本条件指的是在整个文件系统中99.9%的块满足最小副本级别(默认值:dfs.replication.min=1)。在启动一个刚刚格式化的HDFS集群时,因为系统中还没有 任何块,所以NameNode不会进入安全模式

5.5.2 基本语法

· 查看安全模式状态:bin/hdfs dfsadmin -safemode get

· 进入安全模式状态:bin/hdfs dfsadmin -safemode enter

· 离开安全模式状态:bin/hdfs dfsadmin -safemode leave

· 等待安全模式状态:bin/hdfs dfsadmin -safemode wait

第6章 DataNode

6.1 DataNode工作机制

在这里插入图片描述

· 一个数据块在DataNode上以文件形式存储在磁盘上,包括两个文件,一个是数据本身,一个是元数据包括数据块的长度,块数据的校验和,以及时间戳

· DataNode启动后向NameNode注册,通过后,周期性(1小时)的向NameNode上报所有的块信息

· 心跳是每3秒一次,心跳返回结果带有NameNode给该DataNode的命令如复制块数据到另一台机器,或删除某个数据块。如果超过10分钟没有收到某个DataNode的心跳,则认为该节点不可用

· 集群运行中可以安全加入和退出一些机器

6.2 掉线时限参数设置

A.DataNode进程死亡或者网络故障造成DataNode无法与NameNode通信

B.NameNode不会立即把该节点判定为死亡,要经过一段时间,这段时间暂称作超时时长

C.HDFS默认的超时时长为10分钟+30秒

D.如果定义超时时间为TimeOut,则超时时长的计算公式为:

TimeOut = 2 * dfs.namenode.heartbeat.recheck-interval + 10 * dfs.heartbeat.interval

默认dfs.namenode.heartbeat.recheck-interval 大小为5分钟

默认dfs.heartbeat.interval大小为3秒

E.hdfs-site.xml 配置文件中的heartbeat.recheck.interval的单位为毫秒,dfs.heartbeat.interval的单位为秒

<property>
	<name>dfs.namenode.heartbeat.recheck-interval</name>
	<value>300000</value>
</property>
<property>
	<name>dfs.heartbeat.interval</name>
	<value>3</value>
</property>

6.3 服役新数据阶段

A.在hadoop01主机上再克隆一台hadoop04主机

B.修改IP地址和主机名称

C.删除原来HDFS文件系统留存的文件(data和logs)

D.source一下配置文件

E.直接启动DataNode,即可关联到集群

F.在hadoop04上上传文件

G.如果数据不均衡,可以用命令实现集群的再平衡

6.4 退役旧数据节点

6.4.1 添加白名单

添加到白名单的主机节点,都允许访问NameNode,不在白名单的主机节点,会被退出

A.在NameNode的/opt/module/hadoop-2.7.2/etc/hadoop目录下创建dfs.hosts文件

添加主机名称(不添加hadoop04)

hadoop01

hadoop02

hadoop03

B.在NameNode的hdfs-site.xml配置文件中增加dfs.hosts属性

<property>
	<name>dfs.hosts</name>
	<value>/opt/module/hadoop-2.7.2/etc/hadoop/dfs.hosts</value>
</property>

C.配置文件分发:myrsync hdfs-site.xml

D.刷新NameNode:hdfs dfsadmin -refreshNodes

E.更新ResourceManager节点:yarn rmadmin -refreshNodes

F.在web浏览器上查看

G.如果数据不均衡,可以用命令实现集群的再平衡

6.4.2 黑名单退役

在黑名单上面的主机都会被强制退出

A.在NameNode的/opt/module/hadoop-2.7.2/etc/hadoop目录下创建dfs.hosts.exclude文件

添加主机名称(要退役的节点)

hadoop04

B.在NameNode的hdfs-site.xml配置文件中增加dfs.hosts.exclude属性

<property>
	<name>dfs.hosts.exclude</name>
	<value>/opt/module/hadoop-2.7.2/etc/hadoop/dfs.hosts.exclude</value>
</property>

C.刷新NameNode、刷新ResourceManager:hdfs dfsadmin -refreshNodes yarn rmadmin -refreshNodes

D.检查Web浏览器,退役节点的状态为decommission in progress(退役中),说明数据节点正在复制块到其他节点

E.等待退役节点状态为decommissioned(所有块已经复制完成),停止该节点及节点资源管理器。

注意:如果副本数是3,服役的节点小于等于3,是不能退役成功的,需要修改副本数后才能退役

F.如果数据不均衡,可以用命令实现集群的再平衡

注意:不允许白名单和黑名单中同时出现一个主机名称

6.5 DataNode多目录配置

A.DataNode也可以配置成多个目录,每个目录存储的数据不一样。即:数据不是副本

B.配置hdfs-site.xml

<property>
	<name>dfs.datanode.data.dir</name>
	<value>file:///${hadoop.tmp.dir}/dfs/data1,file:///${hadoop.tmp.dir}/dfs/data2</value>
</property>

第7章 HDFS 2.X新特性

7.1 集群间数据拷贝

scp实现两个远程主机之间的文件复制

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

7.2 小文件存档

  • HDFS存储小文件弊端

大量的小文件会耗尽NameNode的大部分内存,因此HDFS存储小文件会非常低效; 但存储小文件所需要的磁盘容量和数据块的大小无关

  • 解决存储小文件办法之一

HDFS存档文件或HAR文件,是一个更高效的文件存档工具,它将文件存入HDFS块,在减少NameNode内存使用的同时,允许对文件进行透明的访问;具体说来,HDFS存档文件对内还是一个一个独立文件,对NameNode而言却是一个整体,减少了NameNode的内存

第8章 HDFS HA高可用

8.1 HA概述

A. 所谓HA(High Available),即高可用(7*24小时不中断服务)

B. 实现高可用最关键的策略是消除单点故障。HA严格来说应该分成各个组件的HA机制:HDFS的HA和YARN的HA

C. Hadoop2.0之前,在HDFS集群中NameNode存在单点故障(SPOF)

D. NameNode主要在以下两个方面影响HDFS集群

·NameNode机器发生意外,如宕机,集群将无法使用,直到管理员重启
·NameNode机器需要升级,包括软件、硬件升级,此时集群也将无法使用
·HDFS HA功能通过配置Active/Standby两个NameNodes实现在集群中对NameNode的热备来解决上述问题。如果出现故障,如机器崩溃或机器需要升级维护,这时可通过此种方式将NameNode很快的切换到另外一台机器

8.2 HDFS-HA工作机制

通过双NameNode消除单点故障

8.2.1 HDFS-HA工作要点

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

·内存中各自保存一份元数据
·Edits日志只有Active状态的NameNode节点可以做写操作
·两个NameNode都可以读取Edits
·共享的Edits放在一个共享存储中管理(qjournal和NFS两个主流实现)

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

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

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

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

8.2.2 HDFS-HA自动故障转移工作机制

在这里插入图片描述

自动故障转移为HDFS部署增加了两个新组件:ZooKeeper和ZKFailoverController(ZKFC)进程,如图3-20所示。ZooKeeper是维护少量协调数据,通知客户端这些数据的改变和监视客户端故障的高可用服务。HA的自动故障转移依赖于ZooKeeper的以下功能:

A. 故障检测:集群中的每个NameNode在ZooKeeper中维护了一个持久会话,如果机器崩溃,ZooKeeper中的会话将终止,ZooKeeper通知另一个NameNode需要触发故障转移

B. 现役NameNode选择:ZooKeeper提供了一个简单的机制用于唯一的选择一个节点为active状态。如果目前现役NameNode崩溃,另一个节点可能从ZooKeeper获得特殊的排外锁以表明它应该成为现役NameNode

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

A. 健康监测:ZKFC使用一个健康检查命令定期地ping与之在相同主机的NameNode,只要该NameNode及时地回复健康状态,ZKFC认为该节点是健康的。如果该节点崩溃,冻结或进入不健康状态,健康监测器标识该节点为非健康的

B. ZooKeeper会话管理:当本地NameNode是健康的,ZKFC保持一个在ZooKeeper中打开的会话。如果本地NameNode处于active状态,ZKFC也保持一个特殊的znode锁,该锁使用了ZooKeeper对短暂节点的支持,如果会话终止,锁节点将自动删除

C. 基于ZooKeeper的选择:如果本地NameNode是健康的,且ZKFC发现没有其它的节点当前持有znode锁,它将为自己获取该锁。如果成功,则它已经赢得了选择,并负责运行故障转移进程以使它的本地NameNode为Active。故障转移进程与前面描述的手动故障转移相似,首先如果必要保护之前的现役NameNode,然后本地NameNode转换为Active状态

8.3 HDFS-HA集群配置

8.3.1 环境准备

A. 修改IP

B. 修改主机名及主机名的IP地址映射

C. 关闭防火墙

D. ssh免密登录

E. 安装JDK,配置环境变量等

8.3.2 规划集群
hadoop01hadoop02hadoop03
NameNodeNameNode
JournalNodeJournalNodeJournalNode
DataNodeDataNodeDataNode
ZKZKZK
ResourceManager
NodeManagerNodeManagerNodeManager
8.3.3 配置Zookeeper集群
  1. 解压安装

    解压zookeeper安装包到/opt/module/目录下

    在/opt/module/zookeeper-3.4.10/这个目录下创建zkData

    重命名/opt/module/zookeeper-3.4.10/conf这个目录下的zoo_sample.cfg为zoo.cfg

  2. 配置zoo.cfg文件

    A. 具体配置

    dataDir=/opt/module/zookeeper-3.4.10/zkData

    增加如下配置

    #########cluster#########
    server.1=hadoop01:2888:3888
    server.2=hadoop02:2888:3888
    server.3=hadoop03:2888:3888
    

    B. 配置参数解读

    server.A=B:C:D。
    

    A是一个数字,表示这个是第几号服务器

    B是这个服务器的IP地址

    C是这个服务器与集群中的Leader服务器交换信息的端口

    D是万一集群中的Leader服务器挂了,需要一个端口来重新进行选举,选出一个新的Leader,而这个端口就是用来执行选举时服务器相互通信的端口

    集群模式下配置一个文件myid,这个文件在dataDir目录下,这个文件里面有一个数据就是A的值,Zookeeper启动时读取此文件,拿到里面的数据与zoo.cfg里面的配置信息比较从而判断到底是哪个server

  3. 集群操作

    A. 在/opt/module/zookeeper-3.4.10/zkData目录下创建一个myid的文件

    B. 编辑myid文件

    在文件中添加与server对用的编号;如1
    

    C. 拷贝(分发)配置号的zookeeper到其他机器上(scp -r zookeeper-3.4.10/ root@hadoop02.jinghang:/opt/app/ 等);并分别修改myid文件中内容为2、3

    D. 分别启动zookeeper(bin/zkServer.sh start)

    E. 查看状态(bin/zkServer.sh status)

8.3.4 配置HDFS-HA集群
  1. 官方地址:http://hadoop.apache.org/

  2. 在opt目录下创建一个ha文件夹

  3. 将/opt/app/下的hadoop-2.7.2拷贝到/opt/ha目录下

  4. 配置hadoop-env.sh

    export JAVA_HOME=/opt/module/jdk1.8.0_144
    
  5. 配置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>
    </configuration>
    
  6. 配置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>hadoop01:9000</value>
    </property>
    
    <!-- nn2的RPC通信地址 -->
    <property>
    	<name>dfs.namenode.rpc-address.mycluster.nn2</name>
    	<value>hadoop02:9000</value>
    </property>
    
    <!-- nn1的http通信地址 -->
    <property>
    	<name>dfs.namenode.http-address.mycluster.nn1</name>
    	<value>hadoop01:50070</value>
    </property>
    
    <!-- nn2的http通信地址 -->
    <property>
    	<name>dfs.namenode.http-address.mycluster.nn2</name>
    	<value>hadoop02:50070</value>
    </property>
    
    <!-- 指定NameNode元数据在JournalNode上的存放位置 -->
    <property>
    	<name>dfs.namenode.shared.edits.dir</name>
    	<value>qjournal://hadoop01:8485;hadoop02:8485;hadoop03: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/jinghang/.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>
    
  7. 拷贝配置好的hadoop环境到其他节点

8.3.5 启动HDFS-HA集群
  1. 在各个JournalNode节点上,输入以下命令启动journalnode服务:sbin/hadoop-daemon.sh start journalnode

  2. 在[nn1]上,对其进行格式化,并启动:bin/hdfs namenode -format,sbin/hadoop-daemon.sh start namenode

  3. 在[nn2]上,同步nn1的元数据信息:bin/hdfs namenode -bootstrapStandby

  4. 启动[nn2]:sbin/hadoop-daemon.sh start namenode

  5. 查看web页面显示

  6. 在[nn1]上,启动所有datanode:sbin/hadoop-daemons.sh start datanode

  7. 将[nn1]切换为Active:bin/hdfs haadmin -transitionToActive nn1

  8. 查看是否Active:bin/hdfs haadmin -getServiceState nn1

8.3.6 配置HDFS-HA自动故障转移
  1. 具体配置

    A. 在hdfs-site.xml中增加

     <property>
         <name>dfs.ha.automatic-failover.enabled</name>
         <value>true</value>
     </property>
    

    B. 在core-site.xml文件中增加

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

    A. 关闭所有HDFS服务:sbin/stop-dfs.sh

    B. 启动Zookeeper集群:bin/zkServer.sh start

    C. 初始化HA在Zookeeper中状态:bin/hdfs zkfc -formatZK

    D. 启动HDFS服务:sbin/start-dfs.sh

  3. 验证

    A. 将Active NameNode进程kill:kill -9 namenode的进程id

    B. 将Active NameNode机器断开网络:service network stop

8.4 YARN-HA配置

8.4.1 YARN-HA工作机制

官方文档:http://hadoop.apache.org/docs/r2.7.2/hadoop-yarn/hadoop-yarn-site/ResourceManagerHA.html

在这里插入图片描述

8.4.2 配置YARN-HA集群
  1. 环境准备

    A. 修改IP

    B. 修改主机名及主机名的IP地址映射

    C. 关闭防火墙

    D. ssh免密登录

    E. 安装JDK,配置环境变量等

    F. 配置zookeepre集群

  2. 规划集群

    hadoop01hadoop02hadoop03
    NameNodeNameNode
    JournalNodeJournalNodeJournalNode
    DataNodeDataNodeDataNode
    ZKZKZK
    ResourceManagerResourceManager
    NodeManagerNodeManagerNodeManager
  3. 具体配置

    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>hadoop01</value>
    </property>
    
    <property>
    	<name>yarn.resourcemanager.hostname.rm2</name>
    	<value>hadoop02</value>
    </property>
    
    <!--指定zookeeper集群的地址--> 
    <property>
    	<name>yarn.resourcemanager.zk-address</name>
    	<value>hadoop01:2181,hadoop02:2181,hadoop03: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>
    

    同步更新其他节点的配置信息

  4. 启动HDFS

    同12.3.5

  5. 启动YARN

    A. 如果之前启动了HDFS服务,关闭所有HDFS服务:sbin/stop-dfs.sh

    B. 再启动各台服务器中的Zookeeper集群:bin/zkServer.sh start

    C. 在任意服务器初始化HA在Zookeeper中状态:bin/hdfs zkfc -formatZK

    D. 在namenode所在的节点启动HDFS服务:sbin/start-dfs.sh

    E. 在resourcemanager所在的服务器执行:sbin/start-yarn.sh

    F. 确保两个resourcemanager都启动了,如果没有启动手动开启:sbin/yarn-daemon.sh start resourcemanager

    G. 查看服务状态:bin/yarn rmadmin -getServiceState rm1

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值