Hadoop原理
Hadoop基础
分布式和集群
properties
分布式: 多台服务器协同配合完成同一个大任务(每个服务器都只完成大任务拆分出来的单独1个子任务)
集 群: 多台服务器联合起来独立做相同的任务(多个服务器分担客户端发来的请求,也可以做备份)
注意: 集群如果客户端请求量(任务量)多,多个服务器同时处理不同请求(不同任务),如果请求量少,一台服务器干活,其他服务器做备份使用
Hadoop框架
概述
properties
Hadoop简介:是Apache旗下的一个用Java语言实现开源软件框架,是一个存储和计算大规模数据的软件平台。
Hadoop起源: Doug Cutting , 1991年 创建的,最早起源一个Nutch项目。
大数据三驾马车: 谷歌的三遍论文加速了hadoop的研发
Hadoop框架意义: 作为大数据解决方案,越来越多的企业将Hadoop 技术作为进入大数据领域的必备技术。
Hadoop发行版本: 分为开源社区版和商业版。
开源社区版:指由Apache软件基金会维护的版本,是官方维护的版本体系,版本丰富,兼容性稍差。
商业版:指由第三方商业公司在社区版Hadoop基础上进行了一些修改、整合以及各个服务组件兼容性测试而发行的版本,如: cloudera的CDH等。
生态圈
版本更新
properties
1.x版本系列: hadoop的第二代开源版本,该版本基本已被淘汰 hadoop组成: HDFS(存储)和MapReduce(计算和资源调度)
2.x版本系列: 架构产生重大变化,引入了Yarn平台等许多新特性 hadoop组成: HDFS(存储)和MapReduce(计算)和YARN(资源调度)
3.x版本系列: 因为2版本的jdk1.7不更新,基于jdk1.8升级产生3版本 hadoop组成: HDFS(存储)和MapReduce(计算)和YARN(资源调度)
hadoop架构[重点]
properties
简单聊下hadoop架构?
hadoop广义上来说:Hadoop通常是指一个更广泛的概念------Hadoop生态圈
hadoop狭义上来说:Hadoop指Apache这款开源框架,它的核心组件有:HDFS,MR,YANR
当前版本hadoop组成: HDFS , MapReduce ,YARN
HDFS:(分布式文件系统),解决海量数据存储
元数据: 描述核心数据的数据
NameNode: 集群当中的主节点,主要用于管理集群当中的各种数据
SecondaryNameNode: 主要能用于辅助NameNode进行文件块元数据存储
DataNode: 集群当中的从节点,主要用于存储集群当中的各种数据
YARN:(作业调度和集群资源管理的框架),解决资源任务调度
ResourceManager: 接收用户的计算请求任务,并负责集群的资源分配
NodeManager: 负责执行主节点分配的任务(给MR的计算程序提供资源)
MapReduce:(分布式运算编程框架),解决海量数据计算
如何计算: 核心思想就是分而治之 Map负责分解,Reduce负责合并
编写MR程序: 使用java/python然后去编写MR程序,学习成本高 如何解决? 使用hive编写sql,底层自动转为MR程序
MapReduce计算需要的数据和产生的结果需要HDFS来进行存储
MapReduce的运行需要由Yarn集群来提供资源调度。
官方示例
properties
在Hadoop的安装包中,官方提供了MapReduce程序的示例examples,以便快速上手体验MapReduce。该示例是使用java语言编写的,被打包成为了一个jar文件。
官方示例jar路径: /export/server/hadoop-3.3.0/share/hadoop/mapreduce
圆周率练习
hadoop jar hadoop-mapreduce-examples-3.3.0.jar pi x y
第一个参数pi:表示MapReduce程序执行圆周率计算;
第二个参数x:用于指定map阶段运行的任务次数,并发度,举例:x=10
第三个参数y:用于指定每个map任务取样的个数,举例: x=50。
shell
[root@node1 mapreduce]# hadoop jar hadoop-mapreduce-examples-3.3.0.jar pi 10 50
...
Job Finished in 29.04 seconds
Estimated value of Pi is 3.16000000000000000000
词频统计[重点]
需求:
WordCount算是大数据统计分析领域的经典需求了,相当于编程语言的HelloWorld。统计文本数据中,
相同单词出现的总次数。用SQL的角度来理解的话,相当于根据单词进行group by分组,相同的单词
分为一组,然后每个组内进行count聚合统计。
已知hdfs中word.txt文件内容如下,计算每个单词出现的次数
步骤:
1.HDFS根目录中创建input目录,存储word.txt文件
可以在window本地提前创建word.txt文件存储,内容如下:
txt
zhangsan lisi wangwu zhangsan
zhaoliu lisi wangwu zhaoliu
xiaohong xiaoming hanmeimei lilei
zhaoliu lilei hanmeimei lilei
2.在shell命令行中执行如下命令
shell
[root@node1 ~]# cd /export/server/hadoop-3.3.0/share/hadoop/mapreduce
[root@node1 mapreduce]# hadoop jar hadoop-mapreduce-examples-3.3.0.jar wordcount /input /output
3.去HDFS中查看是否生成output目录
注意: output输出目录,在执行第2步命令后会自动生成,如果提前手动创建或者已经存在,就会报以下错误:
org.apache.hadoop.mapred.FileAlreadyExistsException: Output directory hdfs://node1.itcast.cn:8020/output already exists
4.进入output目录查看part-r-00000文件,结果如下:
txt
hanmeimei 2
lilei 3
lisi 2
wangwu 2
xiaohong 1
xiaoming 1
zhangsan 2
zhaoliu 3
Hadoop-HDFS
特点
分布式存储 : 一次写入,多次读取
properties
HDFS文件系统可存储超大文件,时效性稍差。
HDFS具有硬件故障检测和自动快速恢复功能。
HDFS为数据存储提供很强的扩展能力。
HDFS存储一般为一次写入,多次读取,只支持追加写入,不支持随机修改。
HDFS可在普通廉价的机器上运行。
hdfs架构
properties
1、Client
发请求就是客户端。
文件切分。文件上传 HDFS 的时候,Client 将文件切分成 一个一个的Block,然后进行存储
与 NameNode 交互,获取文件的位置信息。
与 DataNode 交互,读取或者写入数据。
Client 提供一些命令来管理 和访问HDFS,比如启动或者关闭HDFS。
2、NameNode
就是 master,它是一个主管、管理者。
处理客户端读写请求。
管理 HDFS 元数据(文件路径,文件的大小,文件的名字,文件权限,文件切割后的块(block)信息...)。
配置3副本备份策略。
3、DataNode
就是Slave。NameNode 下达命令,DataNode 执行实际的操作。
存储实际的数据块(block)。
执行数据块的读/写操作。
定时向namenode汇报block信息。
4、Secondary NameNode
并非 NameNode 的备份节点。当NameNode 挂掉的时候,它并不能马上替换 NameNode 并提供服务。
只是辅助 NameNode,对HDFS元数据进行合并,合并后再交给NameNode。
在紧急情况下,可辅助恢复 NameNode 部分数据。
块和副本
properties
block块: HDFS被设计成能够在一个大集群中跨机器可靠地存储超大文件。它将每个文件拆分成一系列的数据块进行存储,这个数据块被称为block,除了最后一个,所有的数据块都是同样大小的。
block 块大小默认: 128M(134217728字节)
注意: 为了容错,文件的所有block都会有副本。每个文件的数据块大小和副本系数都是可配置的。
副本系数默认: 3个
hdfs默认文件配置:https://hadoop.apache.org/docs/r3.3.4/hadoop-project-dist/hadoop-hdfs/hdfs-default.xml
shell命令
properties
hdfs的shell命令概念: 安装好hadoop环境之后,可以执行类似于Linux的shell命令对文件的操作,如ls、mkdir、rm等,对hdfs文件系统进行操作,比如文件的创建、删除、修改文件权限等。
hdfs的shell命令格式1: hadoop fs -命令 参数
hdfs的shell命令格式2: hdfs dfs -命令 参数
hdfs的家目录默认: /user/root 如果在使用命令操作的时候没有加根目录/,默认访问的是此家目录/user/root
查看目录下内容: hdfs dfs -ls 目录的绝对路径
创建目录: hdfs dfs -mkdir 目录的绝对路径
创建文件: hdfs dfs -touch 文件的绝对路径
移动目录/文件: hdfs dfs -mv 要移动的目录或者文件的绝对路径 目标位置绝对路径
复制目录/文件: hdfs dfs -cp 要复制的目录或者文件的绝对路径 目标位置绝对路径
删除目录/文件: hdfs dfs -rm [-r] 要删除的目录或者文件的绝对路径
查看文件的内容: hdfs dfs -cat 要查看的文件的绝对路径 注意: 除了cat还有head,tail也能查看
查看hdfs其他shell命令帮助: hdfs dfs --help
linux本地上传文件到hdfs中: hdfs dfs -put linux本地要上传的目录或者文件的绝对路径 hfds中目标位置绝对路径
hdfs中下载文件到liunx本地: hdfs dfs -get hfds中要下载的目录或者文件的绝对路径 linux本地目标位置绝对路径
Hive环境准备[重点]
前提启动hadoop集群
hadoop在统一虚拟机中已经配置了环境变量
启动hdfs和yarn集群
shell
[root@node1 /]# start-all.sh
启动mr历史服务
shell
[root@node1 /]# mapred --daemon start historyserver
检查服务
shell
[root@node1 /]# mapred --daemon start historyserver
配置Hive环境变量
回顾shell脚本执行方式
properties
方式1: sh 脚本 注意: 需要进入脚本所在目录,但脚本有没有执行权限不影响执行
方式2: ./脚本 注意: 需要进入脚本所在目录,且脚本必须有执行权限
方式3: /绝对路径/脚本 注意: 不需要进入脚本所在目录,但必须有执行权限
方式4: 脚本 注意: 需要配置环境变量(大白话就是把脚本所在路径共享,任意位置都能直接访问)
注意: hive在统一虚拟机中没有配置环境变量,可以下面步骤配置
配置环境变量
shell
[root@node1 /]# vim /etc/profile
在profile文件末尾添加(小技巧G+o快速定位到最后)
export HIVE_HOME=/export/server/apache-hive-3.1.2-bin
export PATH= P A T H : PATH: PATH:HIVE_HOME/bin:$HIVE_HOME/sbin
shell
[root@node1 /]# source /etc/profile
最后建议关机拍摄下快照
先启动hive服务
知识点:
properties
后台启动metastore服务: nohup hive --service metastore &
后台启动hiveserver2服务: nohup hive --service hiveserver2 &
查看metastore和hiveserver2进程是否启动: jps 注意: 服务名都叫RunJar,可以通过进程编号区分
服务启动需要一定时间可以使用lsof查看: lsof -i:10000 注意: 如果无内容继续等待,如果有内容代表启动成功
示例:
shell
[root@node1 bin]# nohup hive --service metastore &
[1] 13490
nohup: 忽略输入并把输出追加到"nohup.out" 回车
[root@node1 bin]# nohup hive --service hiveserver2 &
[2] 13632
nohup: 忽略输入并把输出追加到"nohup.out" 回车
[root@node1 bin]# jps
13490 RunJar
13632 RunJar
[root@node1 bin]#
[root@node1 apache-hive-3.1.2-bin]# lsof -i:10000
COMMAND PID USER FD TYPE DEVICE SIZE/OFF NODE NAME
java 18804 root 520u IPv6 266172 0t0 TCP *:ndmp (LISTEN)
再连接hive服务
知识点:
properties
一代客户端连接命令: hive 注意: hive直接连接成功,直接可以编写sql语句
二代客户端连接命令: beeline 注意: 以后建议用二代客户端
二代客户端远程连接命令: !connect jdbc:hive2://node1:10000
注意: hive用户名是root 密码为空
一代客户端示例:
shell
[root@node1 /]# hive
...
hive> show databases;
OK
default
Time taken: 0.5 seconds, Fetched: 1 row(s)
hive> exit;
二代客户端示例:
shell
[root@node1 /]# beeline
# 先输入!connect jdbc:hive2://node1:10000连接
beeline> !connect jdbc:hive2://node1:10000
# 再输入用户名root,密码不用输入直接回车即可
Enter username for jdbc:hive2://node1:10000: root
Enter password for jdbc:hive2://node1:10000:
# 输入show databases;查看表
0: jdbc:hive2://node1:10000> show databases;
INFO : Concurrency mode is disabled, not creating a lock manager
+----------------+
| database_name |
+----------------+
| default |
+----------------+
1 row selected (1.2 seconds)
Hadoop进阶
HDFS
hdfs默认文件配置:https://hadoop.apache.org/docs/r3.3.4/hadoop-project-dist/hadoop-hdfs/hdfs-default.xml
块和副本
properties
block块: HDFS被设计成能够在一个大集群中跨机器可靠地存储超大文件。它将每个文件拆分成一系列的数据块进行存储,这个数据块被称为block,除了最后一个,所有的数据块都是同样大小的。
block 块大小默认: 128M(134217728字节) 注意: 块同样大小方便统一管理
注意: 为了容错,文件的所有block都会有副本。每个文件的数据块大小和副本系数都是可配置的。
副本系数默认: 3个 副本好处: 副本为了保证数据安全(用消耗存储资源方式保证安全,导致了大数据瓶颈是数据存储)
hdfs默认文件配置:https://hadoop.apache.org/docs/r3.3.4/hadoop-project-dist/hadoop-hdfs/hdfs-default.xml
如何修改块大小和副本数量呢?可以在hdfs-site.xml中配置如下属性:
<property>
<name>dfs.blocksize</name>
<value>134217728</value>
<description>设置HDFS块大小,单位是b</description>
</property>
<property>
<name>dfs.replication</name>
<value>3</value>
</property>
图解:
块 :默认统一大小128m : 为了方便统一管理
副本: 默认3个的原因: 为了保证数据的安全性
三大机制
properties
副本机制: 为了保证数据安全和效率,block块信息存储多个副本,第一副本保存在客户端所在服务器,第二副本保存在和第一副本不同机架服务器上,第三副本保存在和第二副本相同机架不同服务器
负载均衡机制: namenode为了保证不同的datanode中block块信息大体一样,分配存储任务的时候会优先保存在距离近且余量比较大的datanaode上
心跳机制: datanode每隔3秒钟向namenode汇报自己的状态信息,如果某个时刻,datanode连续10次不汇报了,namenode会认为datanode有可能宕机了,namenode就会每5分钟(300000毫秒)发送一次确认消息,连续2次没有收到回复,就认定datanode此时一定宕机了(确认datanode宕机总时间3*10+5*2*60=630秒)
写入数据原理[面试]
properties
1.客户端发起写入数据的请求给namenode
2.namenode接收到客户端请求,开始校验(是否有权限,路径是否存在,文件是否存在等),如果校验没问题,就告知客户端可以写入
3.客户端收到消息,开始把文件数据分割成默认的128m大小的的block块,并且把block块数据拆分成64kb的packet数据包,放入传输序列
4.客户端携带block块信息再次向namenode发送请求,获取能够存储block块数据的datanode列表
5.namenode查看当前距离上传位置较近且不忙的datanode,放入列表中返回给客户端
6.客户端连接datanode,开始发送packet数据包,第一个datanode接收完后就给客户端ack应答(客户端就可以传入下一个packet数据包),同时第一个datanode开始复制刚才接收到的数据包给node2,node2接收到数据包也复制给node3(复制成功也需要返回ack应答),最终建立了pipeline传输通道以及ack应答通道
7.其他packet数据根据第一个packet数据包经过的传输通道和应答通道,循环传入packet,直到当前block块数据传输完成(存储了block信息的datanode需要把已经存储的块信息定期的同步给namenode)
8.其他block块数据存储,循环执行上述4-7步,直到所有block块传输完成,意味着文件数据被写入成功(namenode把该文件的元数据保存上)
9.最后客户端和namenode互相确认文件数据已经保存完成(也会汇报不能使用的datanode)
注意: 不要死记硬背,要结合自己的理解,转换为自己的话术,用于面试
读取数据原理[面试]
properties
1.客户端发送读取文件请求给namenode
2.namdnode接收到请求,然后进行一系列校验(路径是否存在,文件是否存在,是否有权限等),如果没有问题,就告知可以读取
3.客户端需要再次和namenode确认当前文件在哪些datanode中存储
4.namenode查看当前距离下载位置较近且不忙的datanode,放入列表中返回给客户端
5.客户端找到最近的datanode开始读取文件对应的block块信息(每次传输是以64kb的packet数据包),放到内存缓冲区中
6.接着读取其他block块信息,循环上述3-5步,直到所有block块读取完毕(根据块编号拼接成完整数据)
7.最后从内存缓冲区把数据通过流写入到目标文件中
8.最后客户端和namenode互相确认文件数据已经读取完成(也会汇报不能使用的datanode)
注意: 不要死记硬背,要结合自己的理解,转换为自己的话术,用于面试
edits和fsimage文件
properties
namenode管理元数据: 基于edits和FSImage的配合,完成整个文件系统文件的管理。每次对HDFS的操作,均被edits文件记录, edits达到大小上限后,开启新的edits记录,定期进行edits的合并操作
如当前没有fsimage文件, 将全部edits合并为第一个fsimage文件
如当前已存在fsimage文件,将全部edits和已存在的fsimage进行合并,形成新的fsimage
edits编辑文件: 记录hdfs每次操作(namenode接收处理的每次客户端请求)
fsimage镜像文件: 记录某一个时间节点前的当前文件系统全部文件的状态和信息(namenode所管理的文件系统的一个镜像)
SecondaryNameNode辅助合并元数据: SecondaryNameNode会定期从NameNode拉取数据(edits和fsimage)然后合并完成后提供给NameNode使用。
对于元数据的合并,是一个定时过程,基于两个条件:
dfs.namenode.checkpoint.period:默认3600(秒)即1小时
dfs.namenode.checkpoint.txns: 默认1000000,即100W次事务
dfs.namenode.checkpoint.check.period: 检查是否达到上述两个条件,默认60秒检查一次,只要有一个达到条件就执行拉取合并
内存/文件元数据
properties
namenode和secondarynamenode: 配合完成对元数据的保存
元数据: 内存元数据 和 文件元数据 两种分别在内存和磁盘上
内存元数据: namnode运行过程中产生的元数据会先保存在内存中,再保存到文件元数据中。
内存元数据优缺点: 优点: 因为内存处理数据的速度要比磁盘快。 缺点: 内存一断电,数据全部丢失
文件元数据: Edits 编辑日志文件和fsimage 镜像文件
Edits编辑日志文件: 存放的是Hadoop文件系统的所有更改操作(文件创建,删除或修改)的日志,文件系统客户端执行的更改操作首先会被记录到edits文件中
Fsimage镜像文件: 是元数据的一个持久化的检查点,包含Hadoop文件系统中的所有目录和文件元数据信息,但不包含文件块位置的信息。文件块位置信息只存储在内存中,是在 datanode加入集群的时候,namenode询问datanode得到的,并且不间断的更新
fsimage和edits关系: 两个文件都是经过序列化的,只有在NameNode启动的时候才会将fsimage文件中的内容加载到内存中,之后NameNode把增删改查等操作记录同步到edits文件中.使得内存中的元数据和实际的同步,存在内存中的元数据支持客户端的读操作,也是最完整的元数据。
图解
查看历史编辑文件
properties
命令: hdfs oev -i edits文件名 -o 自定义文件名.xml
shell
[root@node1 current]# cd /export/data/hadoop/dfs/name/current
[root@node1 current]# hdfs oev -i edits_0000000000000033404-0000000000000033405 -o 405_edit.xml
[root@node1 current]# cat 405_edit.xml
查看镜像文件
properties
命令: hdfs oiv -i fsimage文件名 -p XML -o 自定义文件名.xml
shell
[root@node1 current]# cd /export/data/hadoop/dfs/name/current
[root@node1 current]# hdfs oiv -i fsimage_0000000000000033405 -p XML -o 405_fsimage.xml
[root@node1 current]# cat 405_fsimage.xml
元数据存储的原理[面试]
注意: 第一次启动namenode的时候是没有编辑日志文件和镜像文件的,下图主要介绍的是第二次及以后访问的时候情况流程
properties
1.namenode第一次启动的时候先把最新的fsimage文件中内容加载到内存中,同时把edits文件中内容也加载到内存中
2.客户端发起指令(增删改查等操作),namenode接收到客户端指令把每次产生的新的指令操作先放到内存中
3.然后把刚才内存中新的指令操作写入到edits_inprogress文件中
4.edits_inprogress文件中数据到了一定阈值的时候,把文件中历史操作记录写入到序列化的edits备份文件中
5.namenode就在上述2-4步中循环操作...
6.当secondarynamenode检测到自己距离上一次检查点(checkpoint)已经1小时或者事务数达到100w,就触发secondarynamenode询问namenode是否对edits文件和fsimage文件进行合并操作
7.namenode告知可以进行合并
8.secondarynamenode将namenode上积累的所有edits和一个最新的fsimage下载到本地,并加载到内存进行合并(这个过程称checkpoint)
9.secondarynamenode把刚才合并后的fsimage.checkpoint文件拷贝给namenode
10.namenode把拷贝过来的最新的fsimage.checkpoint文件,重命名为fsimage,覆盖原来的文件
注意: 不要死记硬背,要结合自己的理解,转换为自己的话术,用于面试
安全模式
安全模式: 不允许HDFS客户端进行任何修改文件的操作,包括上传文件,删除文件等操作。
...
shell
#查看安全模式状态:
[root@node1 /]# hdfs dfsadmin -safemode get
Safe mode is OFF
#开启安全模式:
[root@node1 /]# hdfs dfsadmin -safemode enter
Safe mode is ON
#退出安全模式:
[root@node1 /]# hdfs dfsadmin -safemode leave
Safe mode is OFF
归档机制
归档原因: 每个小文件单独存放到hdfs中(占用一个block块),那么hdfs就需要依次存储每个小文件的元数据信息,相对来说浪费资源
归档格式: hadoop archive -archiveName 归档名.har -p 原始文件的目录 归档文件的存储目录
准备工作: HDFS上准备一个目录binzi,里面存储三个文件 1.txt 2.txt 3.txt ...
shell
[root@node1 /]# hadoop archive -archiveName test.har -p /binzi /
...
[root@node1 /]# hdfs dfs -ls /test1.har
Found 4 items
-rw-r--r-- 3 root supergroup 0 2022-12-27 15:56 /test.har/_SUCCESS
-rw-r--r-- 3 root supergroup 254 2022-12-27 15:56 /test.har/_index
-rw-r--r-- 3 root supergroup 23 2022-12-27 15:56 /test.har/_masterindex
-rw-r--r-- 3 root supergroup 47 2022-12-27 15:56 /test.har/part-0
[root@node1 /]# hdfs dfs -cat /test1.har/part-0
...
归档特性:
Hadoop Archives的URI是:har://scheme-hostname:port/路径/归档名.har
scheme-hostname格式为hdfs-域名:端口
如果没有提供scheme-hostname,它会使用默认的文件系统: har:///路径/归档名.har
shell
[root@node1 /]# hdfs dfs -ls har:///test.har
Found 3 items
-rw-r--r-- 3 root supergroup 15 2022-12-27 15:55 har:///test.har/1.txt
-rw-r--r-- 3 root supergroup 16 2022-12-27 15:55 har:///test.har/2.txt
-rw-r--r-- 3 root supergroup 16 2022-12-27 15:55 har:///test.har/3.txt
[root@node1 /]# hdfs dfs -cat har:///test.har/1.txt
...
[root@node1 /]# hdfs dfs -cat har:///test.har/2.txt
...
[root@node1 /]# hdfs dfs -cat har:///test.har/3.txt
...
垃圾桶机制
在虚拟机中rm命令删除文件,默认是永久删除
在虚拟机中需要手动设置才能使用垃圾桶回收: 把删除的内容放到: /user/root/.Trash/Current/
先关闭服务: 在 node1 中执行 stop-all.sh 新版本不关闭服务也没有问题
再修改文件 core-site.xml : 进入/export/server/hadoop-3.3.0/etc/hadoop目录下进行修改
xml<property> <name>fs.trash.interval</name> <value>1440</value> </property>
其中,1440 表示 1440分钟,也就是 24小时,一天的时间。
设置了垃圾桶机制好处: 文件不会立刻消失,可以去垃圾桶里把文件恢复,继续使用
shell
# 没有开启垃圾桶效果
[root@node1 hadoop]# hdfs dfs -rm /binzi/hello.txt
Deleted /binzi/hello.txt
# 开启垃圾桶
[root@node1 ~]#cd /export/server/hadoop-3.3.0/etc/hadoop
[root@node1 hadoop]# vim core-site.xml
# 注意: 放到<configuration>内容</configuration>中间
<property>
<name>fs.trash.interval</name>
<value>1440</value>
</property>
# 开启垃圾桶效果
[root@node1 hadoop]# hdfs dfs -rm -r /test1.har
2023-05-24 15:07:33,470 INFO fs.TrashPolicyDefault: Moved: 'hdfs://node1.itcast.cn:8020/test1.har' to trash at: hdfs://node1.itcast.cn:8020/user/root/.Trash/Current/test1.har
# 开启垃圾桶后并没有真正删除,还可以恢复
[root@node1 hadoop]# hdfs dfs -mv /user/root/.Trash/Current/test1.har /
MR
单词统计流程
properties
已知文件内容:
hadoop hive hadoop spark hive
flink hive linux hive mysql
input结果:
k1(行偏移量) v1(每行文本内容)
0 hadoop hive hadoop spark hive
30 flink hive linux hive mysql
map结果:
k2(split切割后的单词) v2(拼接1)
hadoop 1
hive 1
hadoop 1
spark 1
hive 1
flink 1
hive 1
linu 1
hive 1
mysql 1
分区/排序/规约/分组结果:
k2(排序分组后的单词) v2(每个单词数量的集合)
flink [1]
hadoop [1,1]
hive [1,1,1,1]
linux [1]
mysql [1]
spark [1]
reduce结果:
k3(排序分组后的单词) v3(聚合后的单词数量)
flink 1
hadoop 2
hive 4
linux 1
mysql 1
spark 1
output结果: 注意: 输出目录一定不要存在,否则报错
flink 1
hadoop 2
hive 4
linux 1
mysql 1
spark 1
MR底层原理[面试]
map阶段
properties
第一阶段是把输入目录下文件按照一定的标准逐个进行逻辑切片,形成切片规划。默认情况下Split size 等于 Block size。每一个切片由一个MapTask处理(当然也可以通过参数单独修改split大小)
第二阶段是对切片中的数据按照一定的规则解析成对。默认规则是把每一行文本内容解析成键值对。key是每一行的起始位置(单位是字节),value是本行的文本内容。(TextInputFormat)
第三阶段是调用Mapper类中的map方法。上阶段中每解析出来的一个,调用一次map方法。每次调用map方法会输出零个或多个键值对
第四阶段是按照一定的规则对第三阶段输出的键值对进行分区。默认是只有一个区。分区的数量就是Reducer任务运行的数量。默认只有一个Reducer任务
第五阶段是对每个分区中的键值对进行排序。首先,按照键进行排序,对于键相同的键值对,按照值进行排序。比如三个键值对<2,2>、<1,3>、<2,1>,键和值分别是整数。那么排序后的结果是<1,3>、<2,1>、<2,2>。
如果有第六阶段,那么进入第六阶段;如果没有,直接输出到文件中
第六阶段是对数据进行局部聚合处理,也就是combiner处理。键相等的键值对会调用一次reduce方法。经过这一阶段,数据量会减少。本阶段默认是没有的。
注意: 不要死记硬背,要结合自己的理解,转换为自己的话术,用于面试
shuffle阶段
properties
shuffle是Mapreduce的核心,它分布在Mapreduce的map阶段和reduce阶段。一般把从Map产生输出开始到Reduce取得数据作为输入之前的过程称作shuffle。
Collect阶段:将MapTask的结果输出到默认大小为100M的环形缓冲区,保存的是key/value,Partition分区信息等
Spill阶段:当内存中的数据量达到一定的阀值(80%)的时候,就会将数据写入本地磁盘,在将数据写入磁盘之前需要对数据进行一次排序的操作,如果配置了combiner,还会将有相同分区号和key的数据进行排序
Merge阶段:把所有溢出的临时文件进行一次合并操作,以确保一个MapTask最终只产生一个中间数据文件
Copy阶段: ReduceTask启动Fetcher线程到已经完成MapTask的节点上复制一份属于自己的数据,这些数据默认会保存在内存的缓冲区中,当内存的缓冲区达到一定的阀值的时候,就会将数据写到磁盘之上
Merge阶段:在ReduceTask远程复制数据的同时,会在后台开启两个线程对内存到本地的数据文件进行合并操作。
Sort阶段:在对数据进行合并的同时,会进行排序操作,由于MapTask阶段已经对数据进行了局部的排序,ReduceTask只需保证Copy的数据的最终整体有效性即可。
注意: 不要死记硬背,要结合自己的理解,转换为自己的话术,用于面试
reduce阶段
properties
第一阶段是Reducer任务会主动从Mapper任务复制其输出的键值对。Mapper任务可能会有很多,因此Reducer会复制多个Mapper的输出。
第二阶段是把复制到Reducer本地数据,全部进行合并,即把分散的数据合并成一个大的数据。再对合并后的数据排序。
第三阶段是对排序后的键值对调用reduce方法。键相等的键值对调用一次reduce方法,每次调用会产生零个或者多个键值对。最后把这些输出的键值对写入到HDFS文件中。
注意: 不要死记硬背,要结合自己的理解,转换为自己的话术,用于面试
YARN
yarn提交mr流程[面试]
properties
1.客户端提交一个MR程序给ResourceManager(校验请求是否合法...)
2.如果请求合法,ResourceManager随机选择一个NodeManager用于生成appmaster(应用程序控制者,每个应用程序都单独有一个appmaster)
3.appmaster会主动向ResourceManager的应用管理器(application manager)注册自己,告知自己的状态信息,并且保持心跳
4.appmaster会根据任务情况计算自己所需要的container资源(cpu,内存...),主动向ResourceManager的资源调度器(resource scheduler)申请并获取这些container资源
5.appmaster获取到container资源后,把对应指令和container分发给其他NodeManager,让NodeManager启动task任务(maptask任务,reducetask任务)
6.NodeManager要和appmaster保持心跳,把自己任务计算进度和状态信息等同步给appmaster,(注意当maptask任务完成后会通知appmaster,appmaster接到消息后会通知reducetask去maptask那儿拉取数据)直到最后任务完成
7.appmaster会主动向ResourceManager注销自己(告知ResourceManager可以把自己的资源进行回收了,回收后自己就销毁了)
调度器
properties
调度器的配置在yarn-site.xml查找,如果没有就去yarn-default.xml中找
网址: https://hadoop.apache.org/docs/stable/hadoop-yarn/hadoop-yarn-common/yarn-default.xml
配置项和默认值如下yarn.resourcemanager.scheduler.class=org.apache.hadoop.yarn.server.resourcemanager.scheduler.capacity.CapacityScheduler
先进先出调度器
properties
FIFO Scheduler: 把应用按提交的顺序排成一个队列,在进行资源分配的时候,先给队列中最头上的应用进行分配资源,待最头上的应用需求满足后再给下一个分配,以此类推。
好处: 能够保证每一个任务都能拿到充足的资源, 对于大任务的运行非常有好处
弊端: 如果先有大任务后有小任务,会导致后续小任务无资源可用, 长期处于等待状态
应用: 测试环境
公平调度器
properties
Fair Scheduler :不需要保留集群的资源,因为它会动态在所有正在运行的作业之间平衡资源 , 当一个大job提交时,只有这一个job在运行,此时它获得了所有集群资源;当后面有小任务提交后,Fair调度器会分配一半资源给这个小任务,让这两个任务公平的共享集群资源。
好处: 保证每个任务都有资源可用, 不会有大量的任务等待在资源分配上
弊端: 如果大任务非常的多, 就会导致每个任务获取资源都非常的有限, 也会导致执行时间会拉长
应用: CDH商业版本的hadoop
容量调度器
properties
Capacity Scheduler: 为每个组织分配专门的队列和一定的集群资源,这样整个集群就可以通过设置多个队列的方式给多个组织提供服务了。在每个队列内部,资源的调度是采用的是先进先出(FIFO)策略。
好处: 可以保证多个任务都可以使用一定的资源, 提升资源的利用率
弊端: 如果遇到非常的大的任务, 此任务不管运行在那个队列中, 都无法使用到集群中所有的资源, 导致大任务执行效率比较低,当任务比较繁忙的时候, 依然会出现等待状态
应用: apache开源版本的hadoop
示例:
调度器的使用是通过yarn-site.xml 配置文件中的
yarn.resourcemanager.scheduler.class 参数进行配置的,默认采用Capacity Scheduler 调度器下面是一个简单的Capacity调度器的配置文件,文件名为capacity-scheduler.xml。
在这个配置中,在root队列下面定义了两个子队列prod和dev,分别占40%和60%的容量
xml<property> <!-- 队列分为两份 prod 和 dev --> <name>yarn.scheduler.capacity.root.queues</name> <value>prod,dev</value> </property> <property> <!--prod占比 40%--> <name>yarn.scheduler.capacity.root.prod.capacity</name> <value>40</value> </property> <property> <!--dev占比 60%--> <name>yarn.scheduler.capacity.root.dev.capacity</name> <value>60</value> </property> <property> <!-- dev的最大占比 75%--> <name>yarn.scheduler.capacity.root.dev.maximum-capacity</name> <value>75</value> </property>
prod由于没有设置maximum-capacity属性,它有可能会占用集群全部资源。
dev的maximum-capacity属性被设置成了75%,所以即使prod队列完全空闲dev也不会占用全部集群资源,也就是说,prod队列仍有25%的可用资源用来应急。
面定义了两个子队列prod和dev,分别占40%和60%的容量
xml<property> <!-- 队列分为两份 prod 和 dev --> <name>yarn.scheduler.capacity.root.queues</name> <value>prod,dev</value> </property> <property> <!--prod占比 40%--> <name>yarn.scheduler.capacity.root.prod.capacity</name> <value>40</value> </property> <property> <!--dev占比 60%--> <name>yarn.scheduler.capacity.root.dev.capacity</name> <value>60</value> </property> <property> <!-- dev的最大占比 75%--> <name>yarn.scheduler.capacity.root.dev.maximum-capacity</name> <value>75</value> </property>
prod由于没有设置maximum-capacity属性,它有可能会占用集群全部资源。
dev的maximum-capacity属性被设置成了75%,所以即使prod队列完全空闲dev也不会占用全部集群资源,也就是说,prod队列仍有25%的可用资源用来应急。