Hadoop

Hadoop_第1张图片


概述

Hadoop是一个由Apache基金会所开发的分布式系统基础架构。主要解决,海量数据的存储和海量数据的分析计算问题。广义上来说,Hadoop通常是指一个更广泛的概念——Hadoop生态圈。

Hadoop发展历史

Hadoop创始人Doug Cutting,为 了实 现与Google类似的全文搜索功能,他在Lucene框架基础上进行优化升级,查询引擎和索引引擎。

2001年年底Lucene成为Apache基金会的一个子项目。对于海量数据的场景,Lucene框架面对与Google同样的困难,存储海量数据困难,检索海量速度慢。学习和模仿Google解决这些问题的办法 :微型版Nutch。可以说Google是Hadoop的思想之源(Google在大数据方面的三篇论文)

  • GFS —>HDFS
  • Map-Reduce —>MR
  • BigTable —>HBase

2003-2004年,Google公开了部分GFS和MapReduce思想的细节,以此为基础Doug Cutting等人用了2年业余时间实现了DFS和MapReduce机制,使Nutch性能飙升。

2005 年Hadoop 作为 Lucene的子项目 Nutch的一部分正式引入Apache基金会。

2006 年 3 月份,Map-Reduce和Nutch Distributed File System (NDFS)分别被纳入到 Hadoop 项目中,Hadoop就此正式诞生,标志着大数据时代来临。名字来源于Doug Cutting儿子的玩具大象

Hadoop 三大发行版本

Hadoop 三大发行版本:Apache、Cloudera、Hortonworks。

Apache 版本最原始(最基础)的版本,对于入门学习最好。2006

Cloudera 内部集成了很多大数据框架,对应产品 CDH。2008

Hortonworks 文档较好,对应产品 HDP。2011

Apache Hadoop

官网:http://hadoop.apache.org

下载:https://hadoop.apache.org/releases.html

Cloudera Hadoop

官网:https://www.cloudera.com/downloads/cdh

下载:https://docs.cloudera.com/documentation/enterprise/6/releasenotes/topics/rg_cdh_6_download.html

2008 年成立的 Cloudera 是最早将 Hadoop 商用的公司,为合作伙伴提供 Hadoop 的商用解决方案,主要是包括支持、咨询服务、培训。

2009 年 Hadoop 的创始人 Doug Cutting 也加盟 Cloudera 公司。Cloudera 产品主要为 CDH,Cloudera Manager,Cloudera Support。

CDH 是 Cloudera 的 Hadoop 发行版,完全开源,比 Apache Hadoop 在兼容性,安全性,稳定性上有所增强。Cloudera 的标价为每年每个节点 10000 美元。

Cloudera Manager 是集群的软件分发及管理监控平台,可以在几个小时内部署好一个 Hadoop 集群,并对集群的节点及服务进行实时监控。

Hortonworks Hadoop

官网:https://hortonworks.com/products/data-center/hdp/

下载:https://hortonworks.com/downloads/#data-platform

2011 年成立的 Hortonworks 是雅虎与硅谷风投公司 Benchmark Capital 合资组建。

公司成立之初就吸纳了大约 25 名至 30 名专门研究 Hadoop 的雅虎工程师,上述工程师均在 2005 年开始协助雅虎开发 Hadoop,贡献了 Hadoop80%的代码。

Hortonworks 的主打产品是 Hortonworks Data Platform(HDP),也同样是 100%开源的产品,HDP 除常见的项目外还包括了 Ambari,一款开源的安装和管理系统。

2018 年 Hortonworks 目前已经被 Cloudera 公司收购。

Hadoop优势

高可靠性:Hadoop底层维护多个数据副本,所以即使Hadoop某个计算元素或存储出现故障,也不会导致数据的丢失。

高扩展性:在集群间分配任务数据,可方便的扩展数以千计的节点。

高效性:在MapReduce的思想下,Hadoop是并行工作的,以加快任务处理速度。

高容错性:能够自动将失败的任务重新分配。

Hadoop 组成(Hadoop1.x、2.x、3.x区别)

Hadoop_第2张图片
HDFS架构概述

Hadoop Distributed File System,简称 HDFS,是一个分布式文件系统。

NameNode(nn):存储文件的元数据,如文件名文件目录结构文件属性(生成时间、副本数、 文件权限),以及每个文件的块列表块所在的DataNode等。

DataNode(dn):在本地文件系统存储文件块数据,以及块数据的校验和

Secondary NameNode(2nn):每隔一段时间对NameNode元数据备份。

YARN 架构概述

Yet Another Resource Negotiator 简称 YARN ,另一种资源协调者,是 Hadoop 的资源管理器。

Hadoop_第3张图片

MapReduce 架构概述

MapReduce 将计算过程分为两个阶段:Map 和 Reduce。

  • Map 阶段并行处理输入数据。

  • Reduce 阶段对 Map 结果进行汇总。

HDFS、YARN、MapReduce 三者关系

Hadoop_第4张图片
大数据技术生态体系

Hadoop_第5张图片
Sqoop: Sqoop 是一款开源的工具,主要用于在 Hadoop、Hive 与传统的数据库(MySQL)间进行数据的传递,可以将一个关系型数据库(例如 :MySQL,Oracle 等)中的数据导进到 Hadoop 的 HDFS 中,也可以将 HDFS 的数据导进到关系型数据库中。

Flume: Flume 是一个高可用的,高可靠的,分布式的海量日志采集、聚合和传输的系统,Flume 支持在日志系统中定制各类数据发送方,用于收集数据;

Kafka: Kafka 是一种高吞吐量的分布式发布订阅消息系统;

Spark: Spark 是当前最流行的开源大数据内存计算框架。可以基于 Hadoop 上存储的大数据进行计算。

Flink: Flink 是当前最流行的开源大数据内存计算框架。用于实时计算的场景较多。

Oozie: Oozie 是一个管理 Hadoop 作业(job)的工作流程调度管理系统。

Hbase: HBase 是一个分布式的、面向列的开源数据库。HBase 不同于一般的关系数据库,它是一个适合于非结构化数据存储的数据库。

Hive: Hive 是基于 Hadoop 的一个数据仓库工具,可以将结构化的数据文件映射为一张数据库表,并提供简单的 SQL 查询功能,可以将 SQL 语句转换为 MapReduce 任务进行运行。其优点是学习成本低,可以通过类 SQL 语句快速实现简单的 MapReduce 统计,不必开发专门的 MapReduce 应用,十分适合数据仓库的统计分析。

ZooKeeper: 它是一个针对大型分布式系统的可靠协调系统,提供的功能包括:配置维护、名字服务、分布式同步、组服务等。


运行环境搭建

安装虚拟机

点击跳转

在这里插入图片描述

linux教程:

点击跳转

在这里插入图片描述

配置模板虚拟机

VMware配置修改
Hadoop_第6张图片

Windows10配置修改(也可以不修改)
Hadoop_第7张图片
修改 windows 的主机映射文件(hosts 文件)

虚拟机配置修改

# root 用户下输入此命令
vim /etc/sysconfig/network-scripts/ifcfg-ens33

Hadoop_第8张图片

# 修改主机名为 hadoop100
hostnamectl set-hostname hadoop100
# 输入命令
vim /etc/hosts

# 添加以下内容
192.168.10.100 hadoop100
192.168.10.101 hadoop101
192.168.10.102 hadoop102
192.168.10.103 hadoop103
192.168.10.104 hadoop104
192.168.10.105 hadoop105
192.168.10.106 hadoop106
192.168.10.107 hadoop107
192.168.10.108 hadoop108

重启虚拟机

reboot

修改 windows 的主机映射文件(hosts 文件)

进入 C:\Windows\System32\drivers\etc 路径,打开 hosts 文件并添加如下内容,然后保存(window10,先拷贝出来,修改保存以后,再覆盖即可)。

192.168.10.100 hadoop100
192.168.10.101 hadoop101
192.168.10.102 hadoop102
192.168.10.103 hadoop103
192.168.10.104 hadoop104
192.168.10.105 hadoop105
192.168.10.106 hadoop106
192.168.10.107 hadoop107
192.168.10.108 hadoop108

安装 epel-release

Extra Packages for Enterprise Linux 是为“红帽系”的操作系统提供额外的软件包,适用于 RHEL、CentOS 和 Scientific Linux。相当于是一个软件仓库,大多数 rpm 包在官方repository 中是找不到的)。

yum install -y epel-release

如果 Linux 安装的是最小系统版,还需要安装如下工具;如果安装的是 Linux桌面标准版,不需要执行。

net-tool:工具包集合,包含 ifconfig 等命令

yum install -y net-tools 

vim:编辑器

yum install -y vim

关闭防火墙,关闭防火墙开机自启

systemctl stop firewalld
systemctl disable firewalld.service

在企业开发时,通常单个服务器的防火墙时关闭的,公司整体对外会设置非常安全的防火墙。

配置用户具有 root 权限,方便后期加 sudo 执行 root 权限的命令

vim /etc/sudoers

修改/etc/sudoers 文件,在%wheel 这行下面添加一行,如下所示:

Hadoop_第9张图片

pinkpig这一行不要直接放到 root 行下面,因为所有用户都属于 wheel 组

在/opt 目录下创建文件夹,并修改所属主和所属组

# 进入opt目录
cd /opt/
# 删除opt目录下的rh文件
sudo rm -rf rh/
# 在 /opt 目录下创建 module、software 文件夹
sudo mkdir /opt/module
sudo mkdir /opt/software
# 修改 module、software 文件夹的所有者和所属组均为 pinkpig用户
sudo chown pinkpig:pinkpig module/ software  # pinkpig是我的用户名和用户组,根据自己的修改

卸载虚拟机自带的 JDK

# root用户下输入此命令
rpm -qa | grep -i java | xargs -n1 rpm -e --nodeps
# rpm -qa:查询所安装的所有 rpm 软件包
# grep -i:忽略大小写
# xargs -n1:表示每次只传递一个参数
# rpm -e –nodeps:强制卸载软件

如果你的虚拟机是最小化安装不需要执行这一步

重启虚拟机

reboot

克隆模板虚拟机

将配置好的Hadoop100虚拟机进行克隆,名字分别为Hadoop102、Hadoop103、Hadoop104。

Hadoop102克隆:右击Hadoop100—>管理—>克隆。
Hadoop_第10张图片
Hadoop103和Hadoop104克隆方法如上。

修改Hadoop102的静态 IP

# 在root用户下输入命令
vim /etc/sysconfig/network-scripts/ifcfg-ens33

#在配置文件中,将PADDR=192.168.10.100修改成PADDR=192.168.10.102

修改主机名为 hadoop102

hostnamectl set-hostname hadoop102

hadoop103 IP修改为192.168.10.103 主机名称为 hadoop103
hadoop104 IP修改为192.168.10.104 主机名称为 hadoop104

安装JDK

在hadoop102上安装

安装 JDK 前,一定确保提前删除了虚拟机自带的 JDK。

用 XShell 传输工具(其他的工具也行) 将 JDK(jdk版本为1.8) 导入到 opt 目录下面的 software 文件夹

进入到 JDK 安装包路径下

cd /opt/software/

解压 JDK 到/opt/module 目录下

tar -zxvf jdk-8u212-linux-x64.tar.gz -C /opt/module/

配置 JDK 环境变量

新建/etc/profile.d/my_env.sh 文件

sudo vim /etc/profile.d/my_env.sh

添加如下内容,并保存退出

#JAVA_HOME
export JAVA_HOME=/opt/module/jdk1.8.0_212
export PATH=$PATH:$JAVA_HOME/bin

source 一下/etc/profile 文件,让新的环境变量 PATH 生效

source /etc/profile 

测试 JDK 是否安装成功

java -version

在这里插入图片描述

安装Hadoop

在hadoop102上安装

下载地址:https://archive.apache.org/dist/hadoop/common/hadoop-3.1.3/

用 XShell 文件传输工具将hadoop(hadoop-3.1.3.tar.gz) 导入到 opt 目录下面的 software 文件夹

进入到 Hadoop 安装包路径下

cd /opt/software/

解压 hadoop 到/opt/module 目录下

tar -zxvf hadoop-3.1.3.tar.gz -C /opt/module/

配置 Hadoop 环境变量

打开/etc/profile.d/my_env.sh 文件

sudo vim /etc/profile.d/my_env.sh

添加如下内容,并保存退出

#HADOOP_HOME
export HADOOP_HOME=/opt/module/hadoop-3.1.3
export PATH=$PATH:$HADOOP_HOME/bin
export PATH=$PATH:$HADOOP_HOME/sbin

source 一下/etc/profile 文件,让新的环境变量 PATH 生效

source /etc/profile 

测试 Hadoop 是否安装成功

hadoop version

如果 Hadoop 命令不能用再重启虚拟机


Hadoop

Hadoop目录结构

Hadoop_第11张图片

bin 目录:存放对 Hadoop 相关服务(hdfs,yarn,mapred)进行操作的脚本

etc 目录:Hadoop 的配置文件目录,存放 Hadoop 的配置文件

lib 目录:存放 Hadoop 的本地库(对数据进行压缩解压缩功能)

sbin 目录:存放启动或停止 Hadoop 相关服务的脚本

share 目录:存放 Hadoop 的依赖 jar 包、文档、和官方案例

运行模式

Hadoop 官方网站:http://hadoop.apache.org/

Hadoop 运行模式包括:本地模式伪分布式模式以及完全分布式模式

  • 本地模式:单机运行,生产环境不用。
  • 伪分布式模式:也是单机运行,但是具备 Hadoop 集群的所有功能,一台服务器模
    拟一个分布式的环境,生产环境不用(缺钱的公司用来测试)。
  • 完全分布式模式:多台服务器组成分布式环境,生产环境使用。

本地运行模式(官方 WordCount)

在 hadoop-3.1.3 文件下面创建一个 wcinput 文件夹

mkdir wcinput

进入 wcinput 目录

cd wcinput

编辑 word.txt 文件

vim word.txt

在文件中输入如下内容并保存退出

A A
BB B
CC CC CC 

回到 Hadoop 目录 /opt/module/hadoop-3.1.3 执行程序

hadoop jar share/hadoop/mapreduce/hadoop-mapreduce-examples-3.1.3.jar wordcount wcinput wcoutput

查看结果

cat wcoutput/part-r-00000

在这里插入图片描述

scp命令

scp全称:secure copy :安全拷贝

scp 可以实现服务器与服务器之间的数据拷贝。(from server1 to server2)

基本语法: scp [option] $pdir$fname $user@$host:$pdir/$fname

  • $pdir$fname:要拷贝的文件路径/名称。
  • $user@$host:$pdir/$fname:目的地用户@主机:目的地路径/名称
参数 说明
-C 这会在复制过程中压缩文件或目录
-P 如果默认 SSH 端口不是 22,则使用此选项指定 SSH 端口
-r 此选项递归复制目录及其内容
-p 保留文件的访问和修改时间

前提:在 hadoop102、hadoop103、hadoop104 都已经创建好的/opt/module、 /opt/software 两个目录,并且已经把这两个目录修改为 pinkpig:pinkpig(根据自己的来修改) (克隆过来的已经有了)

在 hadoop102 上,将 hadoop102 中/opt/module/jdk1.8.0_212 目录拷贝到hadoop103 上

scp -r /opt/module/jdk1.8.0_212/ pinkpig@hadoop103:/opt/module/

在 hadoop103 上,将 hadoop102 中/opt/module/hadoop-3.1.3 目录拷贝到hadoop103 上

scp -r pinkpig@hadoop102:/opt/module/hadoop-3.1.3 /opt/module/

在 hadoop103 上操作,将 hadoop102 中/opt/module 目录下所有目录拷贝到hadoop104 上

scp -r pinkpig@hadoop102:/opt/module/* pinkpig@hadoop104:/opt/module/

rsync命令

远程同步工具

rsync 主要用于备份和镜像。具有速度快、避免复制相同内容和支持符号链接的优点。

rsync 和 scp 区别:用 rsync 做文件的复制要比 scp 的速度快,rsync 只对差异文件做更新,scp 是把所有文件都复制过去。

基本语法:rsync [option] $pdir/$fname $user@$host:$pdir/$fname

  • $pdir$fname:要拷贝的文件路径/名称。
  • $user@$host:$pdir/$fname:目的地用户@主机:目的地路径/名称
参数 说明
-a 归档拷贝
-v 显示复制过程

删除 hadoop103 中/opt/module/hadoop-3.1.3/wcinput

rm -rf wcinput/

在 hadoop102上,同步 hadoop102 中的/opt/module/hadoop-3.1.3 到 hadoop103

rsync -av hadoop-3.1.3/ pinkpig@hadoop103:/opt/module/hadoop-3.1.3/

xsync 分发脚本

在 /home/pinkpig/bin 目录下创建 xsync 文件

# pinkpig是我的家目录,根据自己的修改
cd /home/pinkpig
mkdir bin
cd bin
vim xsync

在该文件中编写如下

#!/bin/bash
#1. 判断参数个数
if [ $# -lt 1 ]
then
	echo Not Enough Arguement!
	exit;
fi
#2. 遍历集群所有机器
for host in hadoop102 hadoop103 hadoop104
do
	echo ==================== $host ====================
 	#3. 遍历所有目录,挨个发送
 	for file in $@
 	do
  		#4. 判断文件是否存在
  		if [ -e $file ]
   			then
			     #5. 获取父目录
				 pdir=$(cd -P $(dirname $file); pwd)
				 #6. 获取当前文件的名称
				 fname=$(basename $file)
				 ssh $host "mkdir -p $pdir"
				 rsync -av $pdir/$fname $host:$pdir
			else
			     echo $file does not exists!
		fi
 	done
done

修改脚本 xsync 具有执行权限

chmod +x xsync

测试脚本,向hadoop103和hadoop104的家目录下分发hadoop102家目录下创建的bin

xsync /home/pinkpig/bin

在 hadoop102上,向hadoop103和hadoop104同步环境变量

sudo ./bin/xsync /etc/profile.d/my_env.sh

用了 sudo,那么 xsync 一定要给它的路径补全

让hadoop103和hadoop104环境变量生效

# 分别在hadoop103和hadoop104执行此命令
source /etc/profile

SSH 无密登录配置

免密登录原理
Hadoop_第12张图片
在hadoop102上 ssh连接 hadoop103 ,连接时出现 Host key verification failed 的解决方法

ssh hadoop103

如果出现如下内容 Are you sure you want to continue connecting (yes/no)? 输入 yes,并回车

退回到 hadoop102

exit

在家目录下查看是否有.ssh,没有则按上述shh连接一下

ls -al

进入.shh目录下

cd .ssh

生成公钥和私钥

ssh-keygen -t rsa

输入命令后敲三次回车,用ll命令查看到如下结果
在这里插入图片描述

文件 说明
known_hosts 记录 ssh 访问过计算机的公钥(public key)
id_rsa 生成的私钥
id_rsa.pub 生成的公钥
authorized_keys 存放授权过的无密登录服务器公钥

将公钥拷贝到要免密登录的目标机器上

ssh-copy-id hadoop102
ssh-copy-id hadoop103
ssh-copy-id hadoop103

为了方便同样在hadoop103和hadoop104上生成公钥和私钥并将公钥拷贝到要免密登录的目标机器上
当前是在pinkpig用户上配置的免密,为了方便,切换到root用户也整一下(也可以不整)

参考:在hadoop102上,root用户配置免密

切换用户

su root

进入/root目录

cd

进入.ssh目录

cd .ssh

生成公钥和私钥

ssh-keygen -t rsa

将公钥拷贝到要免密登录的目标机器上

ssh-copy-id hadoop102
ssh-copy-id hadoop103
ssh-copy-id hadoop103

集群配置

集群部署规划
Hadoop_第13张图片
NameNode 和 SecondaryNameNode 不要安装在同一台服务器。

ResourceManager 也很消耗内存,不要和 NameNode、SecondaryNameNode 配置在同一台机器上。

配置文件说明

Hadoop 配置文件分两类:默认配置文件和自定义配置文件,只有用户想修改某一默认配置值时,才需要修改自定义配置文件,更改相应属性值。

要获取的默认文件 文件存放在 Hadoop 的 jar 包中的位置
core-default.xml hadoop-common-3.1.3.jar/core-default.xml
hdfs-default.xml hadoop-hdfs-3.1.3.jar/hdfs-default.xml
yarn-default.xml hadoop-yarn-common-3.1.3.jar/yarn-default.xml
mapred-default.xml hadoop-mapreduce-client-core-3.1.3.jar/mapred-default.xml

自定义配置文件
core-site.xmlhdfs-site.xmlyarn-site.xmlmapred-site.xml 四个配置文件存放在$HADOOP_HOME/etc/hadoop 这个路径上,用户可以根据项目需求重新进行修改配置。

配置集群

在hadoop102上配置,然后向103和104上分发

核心配置文件,配置 core-site.xml

cd $HADOOP_HOME/etc/hadoop
vim core-site.xml
<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet type="text/xsl" href="configuration.xsl"?>
<configuration>
	 <!-- 指定 NameNode 的地址 -->
	 <property>
		 <name>fs.defaultFS</name>
		 <value>hdfs://hadoop102:8020</value>
	 </property>
	 <!-- 指定 hadoop 数据的存储目录 -->
	 <property>
		 <name>hadoop.tmp.dir</name>
		 <value>/opt/module/hadoop-3.1.3/data</value>
	 </property>
	 <!-- 配置 HDFS 网页登录使用的静态用户为 pinkpig-->
	 <property>
		 <name>hadoop.http.staticuser.user</name>
		 <value>pinkpig</value>
	 </property>
</configuration>

HDFS 配置文件,配置 hdfs-site.xml

vim hdfs-site.xml
<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet type="text/xsl" href="configuration.xsl"?>
<configuration>
	<!-- nn web 端访问地址-->
	<property>
		 <name>dfs.namenode.http-address</name>
		 <value>hadoop102:9870</value>
	 </property>
	<!-- 2nn web 端访问地址-->
	 <property>
		 <name>dfs.namenode.secondary.http-address</name>
		 <value>hadoop104:9868</value>
	 </property>
</configuration>

YARN 配置文件,配置 yarn-site.xml

vim yarn-site.xml
<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet type="text/xsl" href="configuration.xsl"?>
<configuration>
	 <!-- 指定 MR 走 shuffle -->
	 <property>
		 <name>yarn.nodemanager.aux-services</name>
		 <value>mapreduce_shuffle</value>
	 </property>
	 <!-- 指定 ResourceManager 的地址-->
	 <property>
		 <name>yarn.resourcemanager.hostname</name>
		 <value>hadoop103</value>
	 </property>
	 <!-- 环境变量的继承 -->
	 <property>
		 <name>yarn.nodemanager.env-whitelist</name>
   		 <value>JAVA_HOME,HADOOP_COMMON_HOME,HADOOP_HDFS_HOME,HADOOP_CONF_DIR,CLASSPATH_PREPEND_DISTCACHE,HADOOP_YARN_HOME,HADOOP_MAPRED_HOME</value>
	 </property>
</configuration>

MapReduce 配置文件,配置 mapred-site.xml

vim mapred-site.xml
<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet type="text/xsl" href="configuration.xsl"?>
<configuration>
	<!-- 指定 MapReduce 程序运行在 Yarn 上 -->
	 <property>
		 <name>mapreduce.framework.name</name>
		 <value>yarn</value>
	 </property>
</configuration>

在 hadoop3.1.3/etc 目录下分发配置好的 Hadoop 配置文件

xsync hadoop/

在hadoop103 和 hadoop104 上查看文件分发情况

cat /opt/module/hadoop-3.1.3/etc/hadoop/core-site.xml

群起集群

配置 workers

vim /opt/module/hadoop-3.1.3/etc/hadoop/workers

在该文件中增加如下内容:

hadoop102
hadoop103
hadoop104

该文件中添加的内容结尾不允许有空格,文件中不允许有空行。

同步所有节点配置文件

xsync /opt/module/hadoop-3.1.3/etc/hadoop/workers

启动集群

❗如果集群是第一次启动,需要在 hadoop102 节点格式化 NameNode。

# 在hadoop根目录输入
hdfs namenode -format

格式化 NameNode,会产生新的集群 id,导致 NameNode 和 DataNode 的集群 id 不一致,集群找不到已往数据。如果集群在运行过程中报错,需要重新格式化 NameNode 的话,一定要先停止 namenode 和 datanode 进程,并且要删除所有机器的 data 和 logs 目录,然后再进行格式化。

启动 HDFS

# 在hadoop根目录输入
sbin/start-dfs.sh

jps查看启动的进程

Hadoop_第14张图片

Web 端查看 HDFS 的 NameNode:浏览器中输入 http://hadoop102:9870

启动 YARN,在配置了 ResourceManager 的节点(hadoop103)

# 在hadoop根目录输入
sbin/start-yarn.sh

jps查看启动的进程

Hadoop_第15张图片

Web 端查看 YARN 的 ResourceManager:浏览器中输入 http://hadoop103:8088

集群测试

上传文件

[pinkpig@hadoop102 hadoop-3.1.3]$ hadoop fs -mkdir /wcinput
[pinkpig@hadoop102 hadoop-3.1.3]$ hadoop fs -put wcinput/word.txt /wcinput

Web 端查看:浏览器中输入 http://hadoop102:9870

Hadoop_第16张图片

HDFS 的文件存储路径

[pinkpig@hadoop102 subdir0]$ pwd
/opt/module/hadoop-3.1.3/data/dfs/data/current/BP-280162841-192.168.10.102-1674985722478/current/finalized/subdir0/subdir0

如下图所示,blk_1073741825 就是刚才上传 work.txt 的存储文件

在这里插入图片描述

查看 HDFS 在磁盘存储文件内容

在这里插入图片描述

测试YARN

[pinkpig@hadoop102 hadoop-3.1.3]$ hadoop jar share/hadoop/mapreduce/hadoop-mapreduce-examples-3.1.3.jar wordcount /wcinput /wcoutput

Web 端查看:浏览器中输入 http://hadoop103:8088

Hadoop_第17张图片

配置历史服务器

为了查看程序的历史运行情况,需要配置一下历史服务器

配置 mapred-site.xml

# /opt/module/hadoop-3.1.3/etc/hadoop
[pinkpig@hadoop102 hadoop]$ vim mapred-site.xml 
<!-- 历史服务器端地址 -->
<property>
	<name>mapreduce.jobhistory.address</name>
	<value>hadoop102:10020</value>
</property>
<!-- 历史服务器 web 端地址 -->
<property>
	<name>mapreduce.jobhistory.webapp.address</name>
	<value>hadoop102:19888</value>
</property>

分发配置

xsync $HADOOP_HOME/etc/hadoop/mapred-site.xml

启动历史服务器

[pinkpig@hadoop102 hadoop]$ mapred --daemon start historyserver

查看历史服务器是否启动

Hadoop_第18张图片

历史服务器配置好启动完成后,要在hadoop103上重启一下 YARN

Web 端查看 JobHistory:http://hadoop102:19888/jobhistory

测试历史服务器

Hadoop_第19张图片
上传文件

[pinkpig@hadoop102 hadoop-3.1.3]$ hadoop fs -put wcinput/word.txt wcinput/

测试案列

[pinkpig@hadoop102 hadoop-3.1.3]$ hadoop jar share/hadoop/mapreduce/hadoop-mapreduce-examples-3.1.3.jar wordcount /wcinput /wcoutput

等待完成后,Web 端查看:浏览器中输入 http://hadoop103:8088

Hadoop_第20张图片
点击History跳转到这个页面,配置成功
Hadoop_第21张图片

或者浏览器中输入 http://hadoop102:19888/jobhistory
Hadoop_第22张图片

配置日志的聚集

应用运行完成以后,将程序运行日志信息上传到 HDFS 系统上。

日志聚集功能好处:可以方便的查看到程序运行详情,方便开发调试。
Hadoop_第23张图片

开启日志聚集功能,需要重新启动 NodeManager 、ResourceManager 和 HistoryServer。

配置 yarn-site.xml

[pinkpig@hadoop102 hadoop]$ vim yarn-site.xml
<!-- 开启日志聚集功能 -->
<property>
	<name>yarn.log-aggregation-enable</name>
	<value>true</value>
</property>
<!-- 设置日志聚集服务器地址 -->
<property> 
	<name>yarn.log.server.url</name> 
	<value>http://hadoop102:19888/jobhistory/logs</value>
</property>
<!-- 设置日志保留时间为 7 天 -->
<property>
	<name>yarn.log-aggregation.retain-seconds</name>
	<value>604800</value>
</property>

分发配置

[pinkpig@hadoop102 hadoop]$ xsync $HADOOP_HOME/etc/hadoop/yarn-site.xml

关闭 NodeManager 、ResourceManager 和 HistoryServer

[pinkpig@hadoop103 hadoop-3.1.3]$ sbin/stop-yarn.sh 
[pinkpig@hadoop102 hadoop]$ mapred --daemon stop historyserver

启动 NodeManager 、ResourceManage 和 HistoryServer

[pinkpig@hadoop103 hadoop-3.1.3]$ sbin/start-yarn.sh 
[pinkpig@hadoop102 hadoop]$ mapred --daemon start historyserver

删除 HDFS 上已经存在的输出文件

[pinkpig@hadoop102 hadoop-3.1.3]$ hadoop fs -rm -r /wcoutput

测试案列,执行 WordCount 程序

[pinkpig@hadoop102 hadoop-3.1.3]$ hadoop jar share/hadoop/mapreduce/hadoop-mapreduce-examples-3.1.3.jar wordcount /wcinput /wcoutput

查看日志

Hadoop_第24张图片

看到日志输出,配置成功

Hadoop_第25张图片

集群启动/停止方式

各个模块分开启动/停止(配置 ssh 是前提)

启动 HDFS

start-dfs.sh

停止 HDFS

stop-dfs.sh

启动 YARN

start-yarn.sh

停止 YARN

stop-yarn.sh

各个服务组件逐一启动/停止

分别启动 HDFS 组件

hdfs --daemon start namenode/datanode/secondarynamenode

停止 HDFS 组件

hdfs --daemon stop namenode/datanode/secondarynamenode

启动 YARN

yarn --daemon start resourcemanager/nodemanager

停止 YARN

yarn --daemon stop resourcemanager/nodemanager

Hadoop 集群启停脚本

进入家目录下的 /bin

[pinkpig@hadoop102 ~]$ cd /home/pinkpig/bin

编辑启停脚本

[pinkpig@hadoop102 bin]$ vim myhadoop.sh

添加如下内容并保存

#!/bin/bash
if [ $# -lt 1 ]
then
	echo "No Args Input..."
	exit ;
fi
case $1 in
"start")
	echo " =================== 启动 hadoop 集群 ==================="
	echo " --------------- 启动 hdfs ---------------"
	ssh hadoop102 "/opt/module/hadoop-3.1.3/sbin/start-dfs.sh"
	echo " --------------- 启动 yarn ---------------"
	ssh hadoop103 "/opt/module/hadoop-3.1.3/sbin/start-yarn.sh"
	echo " --------------- 启动 historyserver ---------------"
	ssh hadoop102 "/opt/module/hadoop-3.1.3/bin/mapred --daemon start historyserver"
;;
"stop")
	echo " =================== 关闭 hadoop 集群 ==================="
	echo " --------------- 关闭 historyserver ---------------"
	ssh hadoop102 "/opt/module/hadoop-3.1.3/bin/mapred --daemon stop historyserver"
	echo " --------------- 关闭 yarn ---------------"
	ssh hadoop103 "/opt/module/hadoop-3.1.3/sbin/stop-yarn.sh"
	echo " --------------- 关闭 hdfs ---------------"
	ssh hadoop102 "/opt/module/hadoop-3.1.3/sbin/stop-dfs.sh"
;;
*)
	echo "Input Args Error..."
;;
esac

赋予脚本执行权限

[pinkpig@hadoop102 bin]$ chmod +x myhadoop.sh

查看三台服务器Java进程脚本

在 /bin 目录下编辑脚本( /home/pinkpig/bin )

[pinkpig@hadoop102 bin]$ vim jpsall

添加如下内容并保存

#!/bin/bash
for host in hadoop102 hadoop103 hadoop104
do
	echo =============== $host ===============
	ssh $host jps 
done

赋予脚本执行权限

[pinkpig@hadoop102 bin]$ chmod +x jpsall

分发 /home/pinkpig/bin 目录,保证自定义脚本在三台机器上都可以使用

[pinkpig@hadoop102 ~]$ xsync /home/pinkpig/bin/

常用端口号说明

端口名称 Hadoop2.x Hadoop3.x
NameNode 内部通信端口 8020 / 9000 8020 / 9000 / 9820
NameNode HTTP UI 50070 9870
MapReduce 查看执行任务端口 8088 8088
历史服务器通信端口 19888 19888

常用配置文件说明

版本 配置文件
3.x core-site.xml hdfs-site.xml yarn-site.xml mapred-site.xml workers
2.x core-site.xml hdfs-site.xml yarn-site.xml mapred-site.xml slaves

集群时间同步

如果服务器在公网环境(能连接外网),可以不采用集群时间同步,因为服务器会定期和公网时间进行校准;

如果服务器在内网环境必须要配置集群时间同步,否则时间久了,会产生时间偏差,导致集群执行任务时间不同步。

找一个机器,作为时间服务器,所有的机器与这台集群时间进行定时的同步,生产环境根据任务对时间的准确程度要求周期同步。这里测试环境为了尽快看到效果,采用 1 分钟同步一次。

时间服务器配置(必须 root 用户)

查看节点 ntpd 服务状态

[pinkpig@hadoop102 ~]$ systemctl status ntpd

启动 ntpd

[pinkpig@hadoop102 ~]$ systemctl start ntpd

开机自启

[pinkpig@hadoop102 ~]$ systemctl enabled ntpd

修改 ntp.conf 文件

[pinkpig@hadoop102 ~]$ vim /etc/ntp.conf

修改内容如下

1️⃣授权 192.168.10.0-192.168.10.255 网段上的所有机器可以从这台机器上查询和同步时间

在这里插入图片描述
2️⃣集群在局域网中,不使用其他互联网上的时间

Hadoop_第26张图片

3️⃣当该节点丢失网络连接,依然可以采用本地时间作为时间服务器为集群中的其他节点提供时间同步

# 在 ntp.conf 配置文件末尾添加
server 127.127.1.0
fudge 127.127.1.0 stratum 10

修改 hadoop102 的 /etc/sysconfig/ntpd 文件

[pinkpig@hadoop102 ~]$ vim /etc/sysconfig/ntpd

增加内容如下(让硬件时间与系统时间一起同步)

SYNC_HWCLOCK=yes

重新启动 ntpd 服务

[pinkpig@hadoop102 ~]$  systemctl start ntpd

其他机器配置(必须 root 用户)

关闭所有节点上 ntp 服务和自启动

[pinkpig@hadoop103 ~]$ systemctl stop ntpd
[pinkpig@hadoop103 ~]$ systemctl disable ntpd
[pinkpig@hadoop104 ~]$ systemctl stop ntpd
[pinkpig@hadoop104 ~]$ systemctl disable ntpd

在其他机器配置 1 分钟与时间服务器同步一次

[pinkpig@hadoop103 ~]$ crontab -e

编写定时任务如下

*/1 * * * * /usr/sbin/ntpdate hadoop102

修改任意机器时间

[pinkpig@hadoop103 ~]$ date -s "2020-9-11 11:11:11"

1 分钟后查看机器是否与时间服务器同步

[pinkpig@hadoop103 ~]$ date

Hadoop_HDFS

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

HDFS 的使用场景:适合一次写入,多次读出的场景。一个文件经过创建、写入和关闭之后就不需要改变。

HDFS 只是分布式文件管理系统中的一种。

✔️HDFS优点

  • 高容错性

    • 数据自动保存多个副本。它通过增加副本的形式,提高容错性。某一个副本丢失以后,它可以自动恢复。
  • 适合处理大数据

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

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

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

HDFS缺点

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

  • 无法高效的对大量小文件进行存储。

    • 存储大量小文件的话,它会占用NameNode大量的内存来存储文件目录和块信息,因为NameNode的内存总是有限的;

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

  • 不支持并发写入、文件随机修改。

    • 一个文件只能有一个写,不允许多个线程同时写;

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

HDFS组成架构

Hadoop_第27张图片

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

    • 管理HDFS的名称空间。
    • 配置副本策略。
    • 管理数据块(Block)映射信息。
    • 处理客户端读写请求。
  • DataNode:就是Slave。NameNode下达命令,DataNode执行实际的操作。

    • 存储实际的数据块。
    • 执行数据块的读/写操作。
  • Client:就是客户端。

    • 文件切分。文件上传HDFS的时候,Client将文件切分成一个一个的Block,然后进行上传。
    • 与NameNode交互,获取文件的位置信息。
    • 与DataNode交互,读取或者写入数据。
    • Client提供一些命令来管理HDFS,比如NameNode格式化。
    • Client可以通过一些命令来访问HDFS,比如对HDFS增删查改操作。
  • Secondary NameNode:并非NameNode的热备。当NameNode挂掉的时候,它并不能马上替换NameNode并提供服务。

    • 辅助NameNode,分担其工作量,比如定期合并Fsimage和Edits,并推送给NameNode 。
    • 在紧急情况下,可辅助恢复NameNode。

HDFS 文件块大小

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

Hadoop_第28张图片

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

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

HDFS块的大小设置主要取决于磁盘传输速率。

常用命令

hadoop fs 具体命令hdfs dfs 具体命令 两个完全相同。

准备

启动 Hadoop 集群

[pinkpig@hadoop102 hadoop-3.1.3]$ sbin/start-dfs.sh
[pinkpig@hadoop102 hadoop-3.1.3]$ sbin/start-yarn.sh

创建/sanguo文件夹,用来演示一些常用命令的使用。

[pinkpig@hadoop102 hadoop-3.1.3]$ hadoop fs -mkdir /sanguo

查看命令大全

bin/hadoop fs

-help:输出这个命令参数

[pinkpig@hadoop102 hadoop-3.1.3]$ hadoop fs -help rm

-moveFromLocal:从本地剪切粘贴到 HDFS

[pinkpig@hadoop102 hadoop-3.1.3]$ vim shuguo.txt

输入:

shuguo
[pinkpig@hadoop102 hadoop-3.1.3]$ hadoop fs -moveFromLocal ./shuguo.txt /sanguo

-copyFromLocal:从本地文件系统中拷贝文件到 HDFS 路径去

[pinkpig@hadoop102 hadoop-3.1.3]$ vim weiguo.txt

输入:

weiguo
[pinkpig@hadoop102 hadoop-3.1.3]$ hadoop fs -copyFromLocal weiguo.txt /sanguo

-put:等同于 copyFromLocal,生产环境更习惯用 put

[pinkpig@hadoop102 hadoop-3.1.3]$ vim wuguo.txt

输入:

wuguo
[pinkpig@hadoop102 hadoop-3.1.3]$ hadoop fs -put ./wuguo.txt /sanguo

-appendToFile:追加一个文件到已经存在的文件末尾

[pinkpig@hadoop102 hadoop-3.1.3]$ vim liubei.txt

输入:

liubei
[pinkpig@hadoop102 hadoop-3.1.3]$ hadoop fs -appendToFile liubei.txt /sanguo/shuguo.txt

-copyToLocal:从 HDFS 拷贝到本地

[pinkpig@hadoop102 hadoop-3.1.3]$ hadoop fs -copyToLocal /sanguo/shuguo.txt ./

-get:等同于 copyToLocal,生产环境更习惯用 get

[pinkpig@hadoop102 hadoop-3.1.3]$ hadoop fs -get /sanguo/shuguo.txt ./shuguo2.txt

-ls: 显示目录信息

[pinkpig@hadoop102 hadoop-3.1.3]$ hadoop fs -ls /sanguo

-cat:显示文件内容

[pinkpig@hadoop102 hadoop-3.1.3]$ hadoop fs -cat /sanguo/shuguo.txt

-chgrp、-chmod、-chown:Linux 文件系统中的用法一样,修改文件所属权限

[pinkpig@hadoop102 hadoop-3.1.3]$ hadoop fs -chmod 666 /sanguo/shuguo.txt
[pinkpig@hadoop102 hadoop-3.1.3]$ hadoop fs -chown pinkpig:pinkpig /sanguo/shuguo.txt

-mkdir:创建路径

[pinkpig@hadoop102 hadoop-3.1.3]$ hadoop fs -mkdir /jinguo

-cp:从 HDFS 的一个路径拷贝到 HDFS 的另一个路径

[pinkpig@hadoop102 hadoop-3.1.3]$ hadoop fs -cp /sanguo/shuguo.txt /jinguo 

-mv:在 HDFS 目录中移动文件

[pinkpig@hadoop102 hadoop-3.1.3]$ hadoop fs -mv /sanguo/wuguo.txt /jinguo

-tail:显示一个文件的末尾 1kb 的数据

[pinkpig@hadoop102 hadoop-3.1.3]$ hadoop fs -tail /jinguo/shuguo.txt

-rm:删除文件或文件夹

[pinkpig@hadoop102 hadoop-3.1.3]$ hadoop fs -rm /sanguo/shuguo.txt

-rm -r:递归删除目录及目录里面内容

[pinkpig@hadoop102 hadoop-3.1.3]$ hadoop fs -rm -r /sanguo

-du 统计文件夹的大小信息

[pinkpig@hadoop102 hadoop-3.1.3]$ hadoop fs -du -s /jinguo    #-s 查看当前文件总大小
27 81 /jinguo
[pinkpig@hadoop102 hadoop-3.1.3]$ hadoop fs -du -h /jinguo   #-h 查看当前文件下每个文件大小
14 42 /jinguo/shuguo.txt
7  21 /jinguo/weiguo.txt
6  18 /jinguo/wuguo.tx

27 表示文件大小;81 表示 27*3 个副本;/jinguo 表示查看的目录

-setrep:设置 HDFS 中文件的副本数量

[pinkpig@hadoop102 hadoop-3.1.3]$ hadoop fs -setrep 10 /jinguo/shuguo.txt

在这里插入图片描述
这里设置的副本数只是记录在 NameNode 的元数据中,是否真的会有这么多副本,还得看 DataNode 的数量。因为目前只有 3 台设备,最多也就 3 个副本,只有节点数的增加到10台时,副本数才能达到 10。

API 操作

配置客户端环境

在Windows系统下安装hadoop。

配置环境变量

Hadoop_第29张图片
验证 Hadoop 环境变量是否正常。双击 winutils.exe,一闪而过说明正长,如果报错误可能缺少微软运行库。

Hadoop_第30张图片

创建IDEA项目并测试

在 IDEA 中创建一个 Maven 工程 HdfsClientDemo,并导入相应的依赖坐标和日志添加

<dependencies>
    <dependency>
        <groupId>org.apache.hadoopgroupId>
        <artifactId>hadoop-clientartifactId>
        <version>3.1.3version>
    dependency>
    <dependency>
        <groupId>junitgroupId>
        <artifactId>junitartifactId>
        <version>4.12version>
    dependency>
    <dependency>
        <groupId>org.slf4jgroupId>
        <artifactId>slf4j-log4j12artifactId>
        <version>1.7.30version>
    dependency>
dependencies>

在项目的 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

创建 com.pinkpig.HdfsClient类

package com.pinkpig;

import org.apache.hadoop.conf.Configuration;
import org.apache.hadoop.fs.FileSystem;
import org.apache.hadoop.fs.Path;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;

import java.io.IOException;
import java.net.URI;
import java.net.URISyntaxException;

/**
 * @author : pinkpig
 */
public class HdfsClient {

    FileSystem fileSystem;

    @Before
    public void init() throws URISyntaxException, IOException, InterruptedException {
        // 连接集群地址
        URI uri = new URI("hdfs://hadoop102:8020");
        // 创建配置文件
        Configuration configuration = new Configuration();
        // 用户
        String user = "pinkpig";
        // 获取客户端对象
        fileSystem = FileSystem.get(uri, configuration, user);
    }

    @After
    public void close() throws IOException {
        // 关闭资源
        fileSystem.close();
    }

    @Test
    public void testmkdir() throws URISyntaxException, IOException, InterruptedException {

        // 创建文件夹
        fileSystem.mkdirs(new Path("/xiyou/hua"));

    }
    
}

运行成功后显示如下

Hadoop_第31张图片

文件上传

public class HdfsClient {

    FileSystem fileSystem;

    @Before
    public void init() throws URISyntaxException, IOException, InterruptedException {
        // 连接集群地址
        URI uri = new URI("hdfs://hadoop102:8020");
        // 创建配置文件
        Configuration configuration = new Configuration();
        // 用户
        String user = "pinkpig";
        // 获取客户端对象
        fileSystem = FileSystem.get(uri, configuration, user);
    }

    @After
    public void close() throws IOException {
        // 关闭资源
        fileSystem.close();
    }

    /**
     * @Description 上传
     * @return void
     * @Date 2023/3/15 22:32
     */
    @Test
    public void testPut() throws IOException {
        // 参数一:表示删除原数据;参数二:是否允许覆盖;参数三:原数据路径;参数四:目的地路径
        fileSystem.copyFromLocalFile(true, true, new Path("D:\\sun.txt"),
                new Path("/xiyou/hua"));
    }
}

参数优先级

在 resources 目录下创建 hdfs-site.xml



<configuration>
	<property>
		<name>dfs.replicationname>
		<value>1value>
	property>
configuration>

参数优先级: 客户端代码中设置的值 > ClassPath 下的用户自定义配置文件 > 然后是服务器的自定义配置(xxx-site.xml)> 服务器的默认配置(xxx-default.xml)

public class HdfsClient {

    FileSystem fileSystem;

    @Before
    public void init() throws URISyntaxException, IOException, InterruptedException {
        // 连接集群地址
        URI uri = new URI("hdfs://hadoop102:8020");
        // 创建配置文件
        Configuration configuration = new Configuration();
        configuration.set("dfs.replication", "2");
        // 用户
        String user = "pinkpig";
        // 获取客户端对象
        fileSystem = FileSystem.get(uri, configuration, user);
    }

    @After
    public void close() throws IOException {
        // 关闭资源
        fileSystem.close();
    }

    /**
     * @Description 参数优先级
     * hdfs-default.xml < hdfs-site.xml < 在项目资源目录下的配置文件 < 代码里的配置
     * @return void
     * @Date 2023/3/15 22:32
     */
    @Test
    public void testPut() throws IOException {
        // 参数一:表示删除原数据;参数二:是否允许覆盖;参数三:原数据路径;参数四:目的地路径
        fileSystem.copyFromLocalFile(true, true, new Path("D:\\sun.txt"),
                new Path("/xiyou/hua"));
    }
    
}

文件下载

public class HdfsClient {

    FileSystem fileSystem;

    @Before
    public void init() throws URISyntaxException, IOException, InterruptedException {
        // 连接集群地址
        URI uri = new URI("hdfs://hadoop102:8020");
        // 创建配置文件
        Configuration configuration = new Configuration();
        // 用户
        String user = "pinkpig";
        // 获取客户端对象
        fileSystem = FileSystem.get(uri, configuration, user);
    }

    @After
    public void close() throws IOException {
        // 关闭资源
        fileSystem.close();
    }

    /**
     * @Description 文件下载
     * @return void
     * @Date 2023/3/15 23:15
     */
    @Test
    public void testGet() throws IOException {
        //参数一:原文件是否删除,参数二:原文件路径HDFS;参数三:目标地址路径Win ;参数四:是否关闭文件校验
        fileSystem.copyToLocalFile(true, new Path("/xiyou/hua"), new Path("D:\\"), true);
    }
}

文件删除

public class HdfsClient {

    FileSystem fileSystem;

    @Before
    public void init() throws URISyntaxException, IOException, InterruptedException {
        // 连接集群地址
        URI uri = new URI("hdfs://hadoop102:8020");
        // 创建配置文件
        Configuration configuration = new Configuration();
        // 用户
        String user = "pinkpig";
        // 获取客户端对象
        fileSystem = FileSystem.get(uri, configuration, user);
    }

    @After
    public void close() throws IOException {
        // 关闭资源
        fileSystem.close();
    }

    /**
     * @Description 文件删除
     * @return void
     * @Date 2023/3/15 23:15
     */
    @Test
    public void testRm() throws IOException {
        //参数一:要删除的路径;参数二:是否递归删除;
        fileSystem.delete(new Path("/jinguo"), true);
    }
}

文件更名和移动

public class HdfsClient {

    FileSystem fileSystem;

    @Before
    public void init() throws URISyntaxException, IOException, InterruptedException {
        // 连接集群地址
        URI uri = new URI("hdfs://hadoop102:8020");
        // 创建配置文件
        Configuration configuration = new Configuration();
        // 用户
        String user = "pinkpig";
        // 获取客户端对象
        fileSystem = FileSystem.get(uri, configuration, user);
    }

    @After
    public void close() throws IOException {
        // 关闭资源
        fileSystem.close();
    }

    /**
     * @Description 文件更名和移动
     * @return void
     * @Date 2023/3/15 23:15
     */
    @Test
    public void testMv() throws IOException {
        // 参数一:源文件路径;参数二:目标文件路径;
        // 对文件名称的修改
//        fileSystem.rename(new Path("/input/word.txt") ,new Path("input/66.txt"));
        
        // 文件的移动和更名
//        fileSystem.rename(new Path("/input/66.txt") ,new Path("/77.txt"));
        
        // 目录更名
        fileSystem.rename(new Path("/input") ,new Path("/output.txt"));
    }
}

文件详情查看

public class HdfsClient {

    FileSystem fileSystem;

    @Before
    public void init() throws URISyntaxException, IOException, InterruptedException {
        // 连接集群地址
        URI uri = new URI("hdfs://hadoop102:8020");
        // 创建配置文件
        Configuration configuration = new Configuration();
        // 用户
        String user = "pinkpig";
        // 获取客户端对象
        fileSystem = FileSystem.get(uri, configuration, user);
    }

    @After
    public void close() throws IOException {
        // 关闭资源
        fileSystem.close();
    }

    /**
     * @Description 获取文件详细信息
     * @return void
     * @Date 2023/3/15 23:15
     */
    @Test
    public void  testListFiles() throws IOException {
        // 获取所有文件信息
        RemoteIterator<LocatedFileStatus> listFiles = fileSystem.listFiles(new Path("/"), true);
        // 遍历文件
        while (listFiles.hasNext()) {
            LocatedFileStatus fileStatus = listFiles.next();

            System.out.println("==========" + fileStatus.getPath() + "==========");
            System.out.println(fileStatus.getPermission());
            System.out.println(fileStatus.getOwner());
            System.out.println(fileStatus.getGroup());
            System.out.println(fileStatus.getLen());
            System.out.println(fileStatus.getModificationTime());
            System.out.println(fileStatus.getReplication());
            System.out.println(fileStatus.getBlockSize());
            System.out.println(fileStatus.getPath().getName());

            // 获取块信息
            BlockLocation[] blockLocations = fileStatus.getBlockLocations();
            System.out.println(Arrays.toString(blockLocations));
        }
    }
}

文件和文件夹判断

public class HdfsClient {

    FileSystem fileSystem;

    @Before
    public void init() throws URISyntaxException, IOException, InterruptedException {
        // 连接集群地址
        URI uri = new URI("hdfs://hadoop102:8020");
        // 创建配置文件
        Configuration configuration = new Configuration();
        // 用户
        String user = "pinkpig";
        // 获取客户端对象
        fileSystem = FileSystem.get(uri, configuration, user);
    }

    @After
    public void close() throws IOException {
        // 关闭资源
        fileSystem.close();
    }

    /**
     * @Description 文件和文件夹判断
     * @return void
     * @Date 2023/3/15 23:15
     */
    @Test
    public void testFile() throws IOException {
        FileStatus[] listStatus = fileSystem.listStatus(new Path("/"));
        for (FileStatus status : listStatus) {
            if (status.isFile()) {
                System.out.println("文件" + status.getPath().getName());
            } else {
                System.out.println("目录" + status.getPath().getName());
            }
        }
    }
}

HDFS 写数据流程

Hadoop_第32张图片

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

2️⃣ NameNode 返回是否可以上传。

3️⃣ 客户端请求第一个 Block 上传到哪几个 DataNode 服务器上。

4️⃣ NameNode 返回 3 个 DataNode 节点,分别为 dn1、dn2、dn3。

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

6️⃣ dn1、dn2、dn3 逐级应答客户端。

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

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

网络拓扑-节点距离计算

在 HDFS 写数据的过程中,NameNode 会选择距离待上传数据最近距离的 DataNode 接收数据。

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

Hadoop_第33张图片

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

官方说明:http://hadoop.apache.org/docs/r3.1.3/hadoop-project-dist/hadoop-hdfs/HdfsDesign.html#Data_Replication

源码说明:在BlockPlacementPolicyDefault,该类中查找 chooseTargetInOrder 方法。

Hadoop3.1.3副本节点选择

Hadoop_第34张图片

HDFS的读数据流程

Hadoop_第35张图片

1️⃣ 客户端通过 DistributedFileSystem 向 NameNode 请求下载文件,NameNode 通过查询元数据,找到文件块所在的 DataNode 地址。

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

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

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

NameNode 和 SecondaryNameNode工作机制

如果存储在 NameNode 节点的磁盘中,因为经常需要进行随机访问,还有响应客户请求,必然是效率过低。元数据需要存放在内存中。但如果只存在内存中,一旦断电,元数据丢失,整个集群就无法工作了。因此产生在磁盘中备份元数据的FsImage。

这样又会带来新的问题,当在内存中的元数据更新时,如果同时更新 FsImage,就会导致效率过低,但如果不更新,就会发生一致性问题,一旦 NameNode 节点断电,就会产生数据丢失。

因此,引入 Edits 文件(只进行追加操作,效率很高)。每当元数据有更新或者添加元数据时,修改内存中的元数据并追加到 Edits 中。这样,一旦 NameNode 节点断电,可以通过 FsImage 和 Edits 的合并,合成元数据。

但是,如果长时间添加数据到 Edits 中,会导致该文件数据过大,效率降低,而且一旦断电,恢复元数据需要的时间过长。

因此,需要定期进行 FsImage 和 Edits 的合并,如果这个操作由NameNode节点完成,又会效率过低。因此,引入一个新的节点SecondaryNamenode,专门用于 FsImage 和 Edits 的合并。

Hadoop_第36张图片
第一阶段:NameNode 启动

1️⃣ 第一次启动 NameNode 格式化后,创建 Fsimage 和 Edits 文件。如果不是第一次启动,直接加载编辑日志和镜像文件到内存。

2️⃣ 客户端对元数据进行增删改的请求。

3️⃣ NameNode 记录操作日志,更新滚动日志。

4️⃣ NameNode 在内存中对元数据进行增删改。

第二阶段:Secondary NameNode 工作

5️⃣ Secondary NameNode 询问 NameNode 是否需要 CheckPoint。直接带回 NameNode是否检查结果。

6️⃣ Secondary NameNode 请求执行 CheckPoint。

7️⃣ NameNode 滚动正在写的 Edits 日志。将滚动前的编辑日志和镜像文件拷贝到 Secondary NameNode。

8️⃣ Secondary NameNode 加载编辑日志和镜像文件到内存,并合并。生成新的镜像文件 fsimage.chkpoint。

9️⃣ 拷贝 fsimage.chkpoint 到 NameNode。NameNode 将 fsimage.chkpoint 重新命名成 fsimage。

Fsimage 和 Edits

NameNode被格式化之后,将在/opt/module/hadoop-3.1.3/data/tmp/dfs/name/current目录中产生如下文件

在这里插入图片描述

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

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

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

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

oiv 查看 Fsimage 文件

基本语法: hdfs oiv -p 文件类型 -i 镜像文件 -o 转换后文件输出路径

参考实例

[pinkpig@hadoop102 hadoop-3.1.3]$ pwd /opt/module/hadoop-3.1.3/data/dfs/name/current

[pinkpig@hadoop102 hadoop-3.1.3]$ hdfs oiv -p XML -i fsimage_0000000000000000025 -o /opt/module/hadoop-3.1.3/fsimage.xml

[pinkpig@hadoop102 hadoop-3.1.3]$ cat /opt/module/hadoop-3.1.3/fsimage.xml

oev 查看 Edits 文件

基本语法: hdfs oev -p 文件类型 -i 编辑日志 -o 转换后文件输出路径

[pinkpig@hadoop102 hadoop-3.1.3]$ hdfs oev -p XML -i edits_0000000000000000012-0000000000000000013 -o /opt/module/hadoop3.1.3/edits.xml

[pinkpig@hadoop102 hadoop-3.1.3]$ cat /opt/module/hadoop-3.1.3/edits.xml

CheckPoint 时间设置

通常情况下,SecondaryNameNode 每隔一小时执行一次。

hdfs-default.xml

<property>
	<name>dfs.namenode.checkpoint.periodname>
	<value>3600svalue>
property>

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

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

DataNode 工作机制

Hadoop_第37张图片
1️⃣ 一个数据块在 DataNode 上以文件形式存储在磁盘上,包括两个文件,一个是数据本身,一个是元数据包括数据块的长度,块数据的校验和,以及时间戳。

2️⃣ DataNode 启动后向 NameNode 注册,通过后,周期性(6 小时)的向 NameNode 上报所有的块信息。

DN 向 NN 汇报当前解读信息的时间间隔,默认 6 小时;

<property>
	<name>dfs.blockreport.intervalMsecname>
	<value>21600000value>
	<description>Determines block reporting interval in milliseconds.description>
property>

DN 扫描自己节点块信息列表的时间,默认 6 小时

<property>
	<name>dfs.datanode.directoryscan.intervalname>
	<value>21600svalue>
	<description>Interval in seconds for Datanode to scan data directories and reconcile the difference between blocks in memory and on the disk.Support multiple time unit suffix(case insensitive), as described in dfs.heartbeat.interval.description>
property>

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

4️⃣ 集群运行中可以安全加入和退出一些机器。

数据完整性

DataNode 节点保证数据完整性的方法

1️⃣ 当 DataNode 读取 Block 的时候,它会计算 CheckSum。

2️⃣ 如果计算后的 CheckSum,与 Block 创建时值不一样,说明 Block 已经损坏。

3️⃣ Client 读取其他 DataNode 上的 Block。

4️⃣ 常见的校验算法 crc(32),md5(128),sha1(160)

5️⃣ DataNode 在其文件创建后周期验证 CheckSum。

Hadoop_第38张图片

掉线时限参数设置

Hadoop_第39张图片
hdfs-site.xml 配置文件中的 heartbeat.recheck.interval 的单位为毫秒,dfs.heartbeat.interval 的单位为秒。

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

持续更新中。。。

你可能感兴趣的:(hadoop,大数据,java)